├── .gitignore ├── .travis.yml ├── Cargo.toml ├── LICENSE ├── README.md └── src └── lib.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | rust: 3 | - stable 4 | - beta 5 | - nightly 6 | cache: cargo 7 | jobs: 8 | allow_failures: 9 | - rust: nightly 10 | fast_finish: true 11 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "actix-web-middleware-redirect-https" 3 | version = "3.0.1" 4 | description = "A middleware for actix-web which forwards all `http` requests to `https` with optional url string replacement." 5 | authors = ["Peter Trotman "] 6 | edition = "2018" 7 | license = "MIT" 8 | documentation = "https://docs.rs/actix-web-middleware-redirect-https" 9 | repository = "https://github.com/petertrotman/actix-web-middleware-redirect-https" 10 | readme = "README.md" 11 | keywords = ["actix-web", "middleware", "redirect", "https", "ssl"] 12 | categories = ["web-programming", "web-programming::http-server"] 13 | 14 | [dependencies] 15 | actix-service = "1" 16 | actix-web = { version = "3", default-features = false } 17 | futures = "0.3" 18 | 19 | [badges] 20 | travis-ci = { repository = "https://travis-ci.org/petertrotman/actix-web-middleware-redirect-https", branch = "master" } 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any 2 | person obtaining a copy of this software and associated 3 | documentation files (the "Software"), to deal in the 4 | Software without restriction, including without 5 | limitation the rights to use, copy, modify, merge, 6 | publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software 8 | is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice 12 | shall be included in all copies or substantial portions 13 | of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # actix-web-middleware-redirect-https 2 | 3 | [![Build Status](https://travis-ci.org/petertrotman/actix-web-middleware-redirect-https.svg?branch=master)](https://travis-ci.org/petertrotman/actix-web-middleware-redirect-https) 4 | 5 | A middleware for actix-web which forwards all `http` requests to `https` with optional url string replacement. 6 | 7 | Note: Consider using [this fork](https://crates.io/crates/actix-web-middleware-redirect-scheme/) instead 8 | 9 | [crates.io](https://crates.io/crates/actix-web-middleware-redirect-https) 10 | 11 | [docs.rs](https://docs.rs/actix-web-middleware-redirect-https) 12 | 13 | ## Usage 14 | 15 | ```toml 16 | # Cargo.toml 17 | [dependencies] 18 | actix-web-middleware-redirect-https = "3.0.1" 19 | ``` 20 | 21 | ```rust 22 | use actix_web::{App, web, HttpResponse}; 23 | use actix_web_middleware_redirect_https::RedirectHTTPS; 24 | 25 | App::new() 26 | .wrap(RedirectHTTPS::default()) 27 | .route("/", web::get().to(|| HttpResponse::Ok() 28 | .content_type("text/plain") 29 | .body("Always HTTPS!"))); 30 | ``` 31 | By default, the middleware simply replaces the `scheme` of the URL with `https://`, but you may need to it to change other parts of the URL. 32 | For example, in development if you are not using the default ports (80 and 443) then you will need to specify their replacement, as below: 33 | 34 | ```rust 35 | use actix_web::{App, web, HttpResponse}; 36 | use actix_web_middleware_redirect_https::RedirectHTTPS; 37 | 38 | App::new() 39 | .wrap(RedirectHTTPS::with_replacements(&[(":8080".to_owned(), ":8443".to_owned())])) 40 | .route("/", web::get().to(|| HttpResponse::Ok() 41 | .content_type("text/plain") 42 | .body("Always HTTPS on non-default ports!"))); 43 | ``` 44 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # actix-web-middleware-redirect-https 2 | //! 3 | //! Provides a middleware for `actix-web` to redirect all `http` requests to `https`. 4 | 5 | use actix_service::{Service, Transform}; 6 | use actix_web::{ 7 | dev::{ServiceRequest, ServiceResponse}, 8 | http, Error, HttpResponse, 9 | }; 10 | use futures::future::{ok, Either, Ready}; 11 | use std::task::{Context, Poll}; 12 | 13 | /// Middleware for `actix-web` which redirects all `http` requests to `https` with optional url 14 | /// string replacements. 15 | /// 16 | /// ## Usage 17 | /// ``` 18 | /// use actix_web::{App, web, HttpResponse}; 19 | /// use actix_web_middleware_redirect_https::RedirectHTTPS; 20 | /// 21 | /// App::new() 22 | /// .wrap(RedirectHTTPS::default()) 23 | /// .route("/", web::get().to(|| HttpResponse::Ok() 24 | /// .content_type("text/plain") 25 | /// .body("Always HTTPS!"))); 26 | /// ``` 27 | #[derive(Default, Clone)] 28 | pub struct RedirectHTTPS { 29 | replacements: Vec<(String, String)>, 30 | } 31 | 32 | impl RedirectHTTPS { 33 | /// Creates a RedirectHTTPS middleware which also performs string replacement on the final url. 34 | /// This is useful when not running on the default web and ssl ports (80 and 443) since we will 35 | /// need to change the development web port in the hostname to the development ssl port. 36 | /// 37 | /// ## Usage 38 | /// ``` 39 | /// use actix_web::{App, web, HttpResponse}; 40 | /// use actix_web_middleware_redirect_https::RedirectHTTPS; 41 | /// 42 | /// App::new() 43 | /// .wrap(RedirectHTTPS::with_replacements(&[(":8080".to_owned(), ":8443".to_owned())])) 44 | /// .route("/", web::get().to(|| HttpResponse::Ok() 45 | /// .content_type("text/plain") 46 | /// .body("Always HTTPS on non-default ports!"))); 47 | /// ``` 48 | pub fn with_replacements(replacements: &[(String, String)]) -> Self { 49 | RedirectHTTPS { 50 | replacements: replacements.to_vec(), 51 | } 52 | } 53 | } 54 | 55 | impl Transform for RedirectHTTPS 56 | where 57 | S: Service, Error = Error>, 58 | S::Future: 'static, 59 | { 60 | type Request = ServiceRequest; 61 | type Response = ServiceResponse; 62 | type Error = Error; 63 | type InitError = (); 64 | type Transform = RedirectHTTPSService; 65 | type Future = Ready>; 66 | 67 | fn new_transform(&self, service: S) -> Self::Future { 68 | ok(RedirectHTTPSService { 69 | service, 70 | replacements: self.replacements.clone(), 71 | }) 72 | } 73 | } 74 | 75 | pub struct RedirectHTTPSService { 76 | service: S, 77 | replacements: Vec<(String, String)>, 78 | } 79 | 80 | impl Service for RedirectHTTPSService 81 | where 82 | S: Service, Error = Error>, 83 | S::Future: 'static, 84 | { 85 | type Request = ServiceRequest; 86 | type Response = ServiceResponse; 87 | type Error = Error; 88 | type Future = Either>>; 89 | 90 | fn poll_ready(&mut self, cx: &mut Context) -> Poll> { 91 | self.service.poll_ready(cx) 92 | } 93 | 94 | fn call(&mut self, req: ServiceRequest) -> Self::Future { 95 | if req.connection_info().scheme() == "https" { 96 | Either::Left(self.service.call(req)) 97 | } else { 98 | let host = req.connection_info().host().to_owned(); 99 | let uri = req.uri().to_owned(); 100 | let mut url = format!("https://{}{}", host, uri); 101 | for (s1, s2) in self.replacements.iter() { 102 | url = url.replace(s1, s2); 103 | } 104 | Either::Right(ok(req.into_response( 105 | HttpResponse::MovedPermanently() 106 | .header(http::header::LOCATION, url) 107 | .finish() 108 | .into_body(), 109 | ))) 110 | } 111 | } 112 | } 113 | --------------------------------------------------------------------------------