{"id":13685885,"url":"https://github.com/tobmatth/rack-ssl-enforcer","last_synced_at":"2025-05-15T03:06:12.603Z","repository":{"id":52264447,"uuid":"566608","full_name":"tobmatth/rack-ssl-enforcer","owner":"tobmatth","description":"A simple Rack middleware to enforce ssl connections","archived":false,"fork":false,"pushed_at":"2021-05-02T18:54:35.000Z","size":193,"stargazers_count":591,"open_issues_count":8,"forks_count":85,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-04-14T03:06:55.445Z","etag":null,"topics":["rack-middleware","ruby","ssl-connection"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tobmatth.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2010-03-17T13:55:25.000Z","updated_at":"2024-09-21T18:13:02.000Z","dependencies_parsed_at":"2022-08-20T11:31:04.564Z","dependency_job_id":null,"html_url":"https://github.com/tobmatth/rack-ssl-enforcer","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tobmatth%2Frack-ssl-enforcer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tobmatth%2Frack-ssl-enforcer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tobmatth%2Frack-ssl-enforcer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tobmatth%2Frack-ssl-enforcer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tobmatth","download_url":"https://codeload.github.com/tobmatth/rack-ssl-enforcer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254264765,"owners_count":22041793,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["rack-middleware","ruby","ssl-connection"],"created_at":"2024-08-02T14:00:58.493Z","updated_at":"2025-05-15T03:06:12.586Z","avatar_url":"https://github.com/tobmatth.png","language":"Ruby","funding_links":[],"categories":["Ruby","Middlewares"],"sub_categories":[],"readme":"# Rack::SslEnforcer [![Build Status](https://travis-ci.org/tobmatth/rack-ssl-enforcer.svg?branch=master)](https://travis-ci.org/tobmatth/rack-ssl-enforcer)\n\nRack::SslEnforcer is a simple Rack middleware to enforce SSL connections. As of Version 0.2.0, Rack::SslEnforcer marks\nCookies as secure by default (HSTS must be set manually).\n\nTested against Ruby 1.8.7, 1.9.2, 1.9.3, 2.0.0, 2.1.10, 2.2.7, 2.3.4, 2.4.1, ruby-head, REE and the latest versions of Rubinius \u0026 JRuby.\n\n## Installation\n\nThe simplest way to install Rack::SslEnforcer is to use [Bundler](http://gembundler.com).\n\nAdd Rack::SslEnforcer to your `Gemfile`:\n\n```ruby\n gem 'rack-ssl-enforcer'\n```\n\n### Installing on Sinatra / Padrino application\n\nIn order for Rack::SslEnforcer to properly work it has to be at the top\nof the Rack Middleware.\n\nUsing `enable :session` will place Rack::Session::Cookie before Rack::Ssl::Enforcer\nand will prevent Rack::Ssl::Enforcer from marking cookies as secure.\n\nTo fix this issue do not use `enable :sessions` instead add the\nRack::Session::Cookie middleware after Rack::Ssl::Enforcer.\n\nEg:\n\n```ruby\nuse Rack::SslEnforcer\nset :session_secret, 'asdfa2342923422f1adc05c837fa234230e3594b93824b00e930ab0fb94b'\n\n#Enable sinatra sessions\nuse Rack::Session::Cookie, :key =\u003e '_rack_session',\n                           :path =\u003e '/',\n                           :expire_after =\u003e 2592000, # In seconds\n                           :secret =\u003e settings.session_secret\n```\n\n## Basic Usage\n\nIf you don't use Bundler, be sure to require Rack::SslEnforcer manually before actually using the middleware:\n\n```ruby\n require 'rack/ssl-enforcer'\n use Rack::SslEnforcer\n```\n\nTo use Rack::SslEnforcer in your Rails application, add the following line to your application config file (`config/application.rb` for Rails 3 and above, `config/environment.rb` for Rails 2):\n\n```ruby\nconfig.middleware.insert_before  ActionDispatch::Cookies, Rack::SslEnforcer\n```\nCookies should be set before the SslEnforcer processes the headers,\nbut due to the middleware calls chain Rack::SslEnforcer should be inserted before the ActionDispatch::Cookies.\n\nIf all you want is SSL for your whole application, you are done! Otherwise, you can specify some options described below.\n\n## Options\n\n### Host constraints\n\nYou can enforce SSL connections only for certain hosts with `:only_hosts`, or prevent certain hosts from being forced to SSL with `:except_hosts`. Constraints can be a `String`, a `Regex` or an array of `String` or `Regex` (possibly mixed), as shown in the following examples:\n\n```ruby\nconfig.middleware.use Rack::SslEnforcer, :only_hosts =\u003e 'api.example.com'\n# Please note that, for instance, both http://help.example.com/demo and https://help.example.com/demo would be accessible here\n\nconfig.middleware.use Rack::SslEnforcer, :except_hosts =\u003e /[help|blog]\\.example\\.com$/\n\nconfig.middleware.use Rack::SslEnforcer, :only_hosts =\u003e [/[secure|admin]\\.example\\.org$/, 'api.example.com']\n```\n\n### Path constraints\n\nYou can enforce SSL connections only for certain paths with `:only`, prevent certain paths from being forced to SSL with `:except`, or - if you don't care how certain paths are accessed - ignore them with `:ignore`. Constraints can be a `String`, a `Regex` or an array of `String` or `Regex` (possibly mixed), as shown in the following examples:\n\n```ruby\nconfig.middleware.use Rack::SslEnforcer, :only =\u003e '/login'\n# Please note that, for instance, both http://example.com/demo and https://example.com/demo would be accessible here\n\nconfig.middleware.use Rack::SslEnforcer, :only =\u003e %r{^/admin/}\n\nconfig.middleware.use Rack::SslEnforcer, :except =\u003e ['/demo', %r{^/public/}]\n\nconfig.middleware.use Rack::SslEnforcer, :ignore =\u003e '/assets'\n\n# You can also combine multiple constraints\nconfig.middleware.use Rack::SslEnforcer, :only =\u003e '/cart', :ignore =\u003e %r{/assets}, :strict =\u003e true\n\n# And ignore based on blocks\nconfig.middleware.use Rack::SslEnforcer, :ignore =\u003e lambda { |request| request.env[\"HTTP_X_IGNORE_SSL_ENFORCEMENT\"] == \"magic\" }\n```\n\n### Method constraints\n\nYou can enforce SSL connections only for certain HTTP methods with `:only_methods`, or prevent certain HTTP methods from being forced to SSL with `:except_methods`. Constraints can be a `String` or an array of `String`, as shown in the following examples:\n\n```ruby\n# constraint as a String\nconfig.middleware.use Rack::SslEnforcer, :only_methods =\u003e 'POST'\n# Please note that, for instance, GET requests would be accessible via SSL and non-SSL connection here\n\nconfig.middleware.use Rack::SslEnforcer, :except_methods =\u003e ['GET', 'HEAD']\n```\n\nNote: The `:hosts` constraint takes precedence over the `:path` constraint. Please see the tests for examples.\n\n\n### Environment constraints\n\nYou can enforce SSL connections only for certain environments with `:only_environments` or prevent certain environments from being forced to SSL with `:except_environments`.\nEnvironment constraints may be a `String`, a `Regex` or an array of `String` or `Regex` (possibly mixed), as shown in the following examples:\n\n```ruby\nconfig.middleware.use Rack::SslEnforcer, :except_environments =\u003e 'development'\n\nconfig.middleware.use Rack::SslEnforcer, :except_environments =\u003e /^[0-9a-f]+_local$/i\n\nconfig.middleware.use Rack::SslEnforcer, :only_environments =\u003e ['production', /^QA/]\n```\n\nNote: The `:environments` constraint requires one the following environment variables to be set: `RACK_ENV`, `RAILS_ENV`, `ENV`.\n\n### User agent constraints\n\nYou can enforce SSL connections only for certain user agents with `:only_agents` or prevent certain user agents from being forced to SSL with `:except_agents`.\nUser agent constraints may be a `String`, a `Regex` or an array of `String` or `Regex` (possibly mixed), as shown in the following examples:\n\n```ruby\nconfig.middleware.use Rack::SslEnforcer, :except_agents =\u003e 'Googlebot'\n\nconfig.middleware.use Rack::SslEnforcer, :except_agents =\u003e /[Googlebot|bingbot]/\n\nconfig.middleware.use Rack::SslEnforcer, :only_agents =\u003e ['test-secu-bot', /custom-crawler[0-9a-f]/]\n```\n\n### Force-redirection to non-SSL connection if constraint is not matched\n\nUse the `:strict` option to force non-SSL connection for all requests not matching the constraints you set. Examples:\n\n```ruby\nconfig.middleware.use Rack::SslEnforcer, :only =\u003e [\"/login\", /\\.xml$/], :strict =\u003e true\n# https://example.com/demo would be redirected to http://example.com/demo\n\nconfig.middleware.use Rack::SslEnforcer, :except_hosts =\u003e 'demo.example.com', :strict =\u003e true\n# https://demo.example.com would be redirected to http://demo.example.com\n```\n\n### Automatic method constraints\n\nIn the case where you have matching URLs with different HTTP methods – for instance Rails RESTful routes: `GET /users`, `POST /users`, `GET /user/:id` and `PUT /user/:id` – you may need to force POST and PUT requests to SSL connection but redirect to non-SSL connection on GET.\n\n```ruby\nconfig.middleware.use Rack::SslEnforcer, :only =\u003e [%r{^/users/}], :mixed =\u003e true\n```\n\nThe above will allow you to POST/PUT from the secure/non-secure URLs keeping the original schema.\n\n### HTTP Strict Transport Security (HSTS)\n\nTo set HSTS expiry and subdomain inclusion (defaults respectively to `one year` and `true`).\n\n```ruby\nconfig.middleware.use Rack::SslEnforcer, :hsts =\u003e { :expires =\u003e 500, :subdomains =\u003e false, :preload =\u003e false }\nconfig.middleware.use Rack::SslEnforcer, :hsts =\u003e true # equivalent to { :expires =\u003e 31536000, :subdomains =\u003e true, :preload =\u003e false }\n```\nPlease note that the strict option disables HSTS.\n\n### Redirect to specific URL (e.g. if you're using a proxy)\n\nYou might need the `:redirect_to` option if the requested URL can't be determined.\n\n```ruby\nconfig.middleware.use Rack::SslEnforcer, :redirect_to =\u003e 'https://example.org'\n```\n\n### Redirect with specific HTTP status code\n\nBy default it redirects with HTTP status code 301(Moved Permanently). Sometimes you might need to redirect with different HTTP status code:\n\n```ruby\nconfig.middleware.use Rack::SslEnforcer, :redirect_code =\u003e 302\n```\n\n### Custom HTTP port\n\nIf you're using a different port than the default (80) for HTTP, you can specify it with the `:http_port` option:\n\n```ruby\nconfig.middleware.use Rack::SslEnforcer, :http_port =\u003e 8080\n```\n\n### Custom HTTPS port\n\nIf you're using a different port than the default (443) for HTTPS, you can specify it with the `:https_port` option:\n\n```ruby\nconfig.middleware.use Rack::SslEnforcer, :https_port =\u003e 444\n```\n\n### Secure cookies disabling\n\nFinally you might want to share a cookie based session between HTTP and HTTPS.\nThis is not possible by default with Rack::SslEnforcer for [security reasons](http://en.wikipedia.org/wiki/HTTP_cookie#Cookie_theft_and_session_hijacking).\n\nNevertheless, you can set the `:force_secure_cookies` option to `false` in order to be able to share a cookie based session between HTTP and HTTPS:\n\n```ruby\nconfig.middleware.use Rack::SslEnforcer, :only =\u003e \"/login\", :force_secure_cookies =\u003e false\n```\n\nBut be aware that if you do so, you have to make sure that the content of you cookie is encoded.\nThis can be done using a coder with [Rack::Session::Cookie](https://github.com/rack/rack/blob/master/lib/rack/session/cookie.rb#L28-42).\n\n### Running code before redirect\n\nYou may want to run some code before rack-ssl-enforcer forces a redirect.  This code could do something like log that a redirect was done, or if this is used in a Rails app, keeping the flash when redirecting:\n\n\n```ruby\nconfig.middleware.use Rack::SslEnforcer, :only =\u003e '/login', :before_redirect =\u003e Proc.new { |request|\n  #keep flash on redirect\n  request.session[:flash].keep if !request.session.nil? \u0026\u0026 request.session.key?('flash') \u0026\u0026 !request.session['flash'].empty?\n}\n```\n\n### Custom or empty response body\n\nThe default response body is:\n\n```html\n\u003chtml\u003e\u003cbody\u003eYou are being \u003ca href=\"https://www.example.org/\"\u003eredirected\u003c/a\u003e.\u003c/body\u003e\u003c/html\u003e\n```\n\nTo supply a custom message, provide a string as `:redirect_html`:\n\n```ruby\nconfig.middleware.use Rack::SslEnforcer, :redirect_html =\u003e 'Redirecting!'\n```\n\nTo supply a series of responses for Rack to chunk, provide a [permissable Rack body object](http://rack.rubyforge.org/doc/SPEC.html):\n\n```ruby\nconfig.middleware.use Rack::SslEnforcer, :redirect_html =\u003e ['\u003chtml\u003e','\u003cbody\u003e','Hello!','\u003c/body\u003e','\u003c/html\u003e']\n```\n\nTo supply an empty response body, provide :redirect_html as false:\n\n```ruby\nconfig.middleware.use Rack::SslEnforcer, :redirect_html =\u003e false\n```\n\n## Deployment\n\nIf you run your application behind a proxy (e.g. Nginx) you may need to do some configuration on that side. If you don't you may experience an infinite redirect loop.\n\nThe reason this happens is that Rack::SslEnforcer can't detect if you are running SSL or not. The solution is to have your front-end server send extra headers for Rack::SslEnforcer to identify the request protocol.\n\n### Nginx\n\nIn the `location` block for your app's SSL configuration, include the following proxy header configuration:\n\n`proxy_set_header   X-Forwarded-Proto https;`\n\n### Nginx behind Load Balancer\n\nThe following instruction has been tested behind AWS ELB, but can be adapted to work behind any load balancer.\nSpecifically, the options below account for termination of SSL at the load balancer (HTTP only communication between load balancer and server), and HTTP only health checks.\n\nIn the `location` block for your app's SSL configuration, reference the following proxy header configurations:\n\n```\nproxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;\nproxy_set_header Host $http_host;\nproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for\nproxy_redirect off;\n```\n\nIn `config/application.rb` for Rails 3 and above, `config/environment.rb` for Rails 2, work off the following line:\n\n```ruby\nconfig.middleware.use Rack::SslEnforcer, ignore: lambda { |request| request.env[\"HTTP_X_FORWARDED_PROTO\"].blank? }, strict: true\n```\n\nThis ignores ELB healthchecks and development environment as ELB healthchecks aren't forwarded requests, so it wouldn't have the forwarded proto header.\n\nSame goes for when running without a proxy (like developemnt locally), making `:except_environments =\u003e 'development'` unnecessary.\n\nIn Sinatra or other non-rails ruby applications, work off the following line:\n```ruby\nuse Rack::SslEnforcer, :except_environments =\u003e ['development', 'test'], :ignore =\u003e '/healthcheck'\n```\n\n### Passenger\n\nOr, if you're using mod_rails/passenger (which will ignore the proxy_xxx directives):\n\n`passenger_set_cgi_param HTTP_X_FORWARDED_PROTO https;`\n\nIf you're sharing a single `server` block for http AND https access you can add:\n\n`passenger_set_cgi_param HTTP_X_FORWARDED_PROTO $scheme;`\n\nThis makes sure that Rack::SslEnforcer knows it's being accessed over SSL. Just restart Nginx for these changes to take effect.\n\n## TODO\n\n* Cleanup tests\n\n#### Contributors\n\n[https://github.com/tobmatth/rack-ssl-enforcer/graphs/contributors](https://github.com/tobmatth/rack-ssl-enforcer/graphs/contributors)\n\n## Credits\n\nFlagging cookies as secure functionality and HSTS support is greatly inspired by [Joshua Peek's Rack::SSL](https://github.com/josh/rack-ssl).\n\n## Note on Patches / Pull Requests\n\n* Fork the project.\n* Code your feature addition or bug fix.\n* **Add tests for it.** This is important so we don't break it in a future version unintentionally.\n* Commit, do not mess with Rakefile or version number. If you want to have your own version, that's fine but bump version in a commit by itself so we can ignore it when merging.\n* Send a pull request. Bonus points for topic branches.\n\n## Copyright\n\nCopyright (c) 2010-2013 Tobias Matthies. See [LICENSE](https://github.com/tobmatth/rack-ssl-enforcer/blob/master/LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftobmatth%2Frack-ssl-enforcer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftobmatth%2Frack-ssl-enforcer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftobmatth%2Frack-ssl-enforcer/lists"}