Skip to content

Conversation

@jumarko
Copy link

@jumarko jumarko commented Apr 21, 2022

Use relative URLs for redirects.

This fixes #4.
For long, the HTTP spec has allowed relative URLs in the Location header,
see https://datatracker.ietf.org/doc/html/rfc7231#section-7.1.2.

Absolute URLs have been introduced here: cemerick@5b04323
It was trying to fix the issue reported in 2013: cemerick#42
where they claimed that friend didn't follow the HTTP spec.

However, this lead to all sorts of problems with Clojure apps running behind an SSL/TLS proxy,
e.g. cemerick#84.

To sum up: The original friend implementation got it right by using
relative URLs for redirects but it wasn't, at the time, strictly following the HTTP spec.
However, the HTTP spec has since been updated and there's no more reason
to use absolute URLs - they are brittle and break apps.

UPDATE: ring-defaults vs relative redirects

I fixed all the paths in friend's code that I could find.
However, even after doing that, my application was still redirecting to HTTP, instead of HTTPS.
I found that the problem is in ring-defaults: https://github.com/ring-clojure/ring-defaults#customizing

:absolute-redirects - Any redirects to relative URLs will be turned into redirects to absolute URLs, to better conform to the HTTP spec.

:absolute-redirects is set to true in site-defaults: https://github.com/ring-clojure/ring-defaults/blob/master/src/ring/middleware/defaults.clj#L52

So to make this work, you also need to customize wrap-defaults, e.g. like this:

(defn not-enforce-absolute-redirects [defaults]
  (assoc-in defaults [:responses :absolute-redirects] false))

(def my-app 
  (-> handler
      (wrap-defaults (-> site-defaults not-enforce-absolute-redirects))))

I posted a message about this on Clojurians slack's ring channel: https://clojurians.slack.com/archives/C0A5GSC6T/p1650524416846019

jumarko added 3 commits April 21, 2022 07:20
Without it, `lein test` produces the following error
when executing test/test_friend/functional.clj:

```
Syntax error (ClassNotFoundException) compiling at (ring/adapter/jetty.clj:1:1).
org.eclipse.jetty.util.component.AggregateLifeCycle
```
This fixes clj-commons#4.
For long, the HTTP spec has allowed relative URLs in the Location header,
see https://datatracker.ietf.org/doc/html/rfc7231#section-7.1.2.

Absolute URLs have been introduced here: cemerick@5b04323
It was trying to fix the issue reported in 2013: cemerick#42
where they claimed that friend doesn't follow the HTTP spec.

However, this lead to all sorts of problems with the clojure app
running behind an SSL/TLS proxy,
e.g. cemerick#84.

To sum up: Original friend implementation got it right by using
relative URLs for redirects but it wasn't, at the time,
strictly following the HTTP spec.
However, the HTTP spec has since been updated and there's no more reason
to use absolute URLs - they are brittle and break apps.
This is to avoid redirecting to HTTP when the user request was in fact to an HTTPS endpoint.
Such a situation happens when you run an SSL proxy in front of your plain HTTP app server.
In that case, `ring.util.request/request-url` returns _almost_ a proper endpoint,
but uses "http" not "https".
@jumarko jumarko marked this pull request as ready for review April 21, 2022 07:24
@jumarko jumarko requested a review from slipset as a code owner April 21, 2022 07:24
@@ -1,5 +1,11 @@
## [Friend](http://github.com/cemerick/friend) changelog

### `0.3.x`
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how does versioning works these days - should I replace x with something specific?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries, I'll take care of that at release

Comment on lines 15 to 20
(defn resolve-absolute-uri
[^String uri request]
(-> (original-url request)
java.net.URI.
(.resolve uri)
str))
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be worried about an external client using this function?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps it's safer to leave it and mark it as deprecated?

Comment on lines +75 to +76
(str (if (.contains login-uri "?") login-uri (str login-uri "?"))
param))))
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is basically the same implementation as it was 9 years ago: cemerick@5b04323#diff-7e2343c759ed64f4985000a745bce4778210e832d9e98b4c59e8793344cb5ef9L65-L66

Copy link
Member

@slipset slipset left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you could reinstate the one deleted fn and update the documentation as mentioned in comments, I'm good.

@jumarko jumarko requested a review from slipset April 24, 2022 10:35
@slipset slipset merged commit d2ec66b into clj-commons:master Apr 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Friend produces incorrect absolute redirects when behind a proxy

2 participants