web-server/dispatch should facilitate handling trailing "/"s on URLs
まだ誰も着手していません。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 25/100
- issue の種類
- 機能追加
- 明瞭さ
- 説明が足りない
- 活発さ
- 停滞
- 領域
- backend
調査の方向性
web-server/dispatchから始め、特に dispatch-rules と dispatch-rules+applies を確認し、web-server-doc/web-server/scribblings/http.scrbl にある HTTP リダイレクトの議論を見直してください。提供された request の例と既存の dispatch の動作を調べてください。完了には、合意された API 設計と、末尾のスラッシュおよび関連する URL バリアントをカバーするテストが必要です。
索引モデルが issue の本文から書いたものです。
説明
I recently discovered that dispatch-rules and related forms make it hard to handle trailing /s on URLs sensibly.
The URL https://example.com/foo/ (with a trailing /) is treated differently than https://example.com/foo (without a trailing /). Strictly speaking, this is correct: those are two distinct URLs, and in principle one could serve completely unrelated content at each. In practice, though, users don't expect such URLs to be distinct. Serving different non-error content at one than the other is a terrible idea, and even returning a successful response from one variant but, e.g., a 404 error from the other (as my sight was doing) is likely to cause confusion. I expect most programs will want to either redirect the less-preferred variant to the canonical variant or simply treat both variants as equivalent.
Unfortunately, web-server/dispatch doesn't provide a great way to implement such behavior. Here's an example in code of the current state of affairs:
#lang racket
(require web-server/dispatch
web-server/http
web-server/servlet-env
net/url
rackunit)
(define ((handler str) req)
(response/output
(λ (out) (write-string str out))))
(define start
(dispatch-case
[() (handler "a")]
[("") (handler "b")]
[("foo") (handler "c")]
[("foo" "") (handler "d")]
[("foo" "" "") (handler "e")]
[("foo" "" "bar") (handler "f")]))
(define (do-request str)
(port->string (get-pure-port (string->url str))))
(check-equal?
(let ([th (thread
(λ ()
(serve/servlet start
#:servlet-regexp #rx""
#:banner? #f
#:launch-browser? #f)))])
(sleep 5)
(begin0 (list (do-request "http://localhost:8000")
(do-request "http://localhost:8000/")
(do-request "http://localhost:8000/foo")
(do-request "http://localhost:8000/foo/")
(do-request "http://localhost:8000/foo//")
(do-request "http://localhost:8000/foo//bar"))
(kill-thread th)))
'("b" "b" "c" "d" "e" "f"))
This illustrates a few things:
- Because of how HTTP requests work, the root URL is always equivalent with or without a trailing
/and has a single, empty path element (""). ()is allowed as a pattern, but (due to the above) will never match anything. I think it might be better to make this a syntax error (or a warning that will become an error in a future release).- A trailing
/adds an empty path element ("") to the end of the URL. - There is no
cleanse-path-like case for multiple adjacent/separators.
I have changed my application to handle trailing / separators by using dispatch-rules+applies instead of dispatch-rules (which involved removing my else clause) and, if the original request does not satisfy the predicate from dispatch-rules+applies but a version with a normalized path would, responding with a redirect to the normalized path.
I think it would be better to extend web-server/dispatch to support this sort of thing, but I'm not sure yet what the best way would be to do so. A few things I've been thinking about so far:
- The current language for
dispatch-rulespatterns doesn't have a notion of "splicing" patterns: each string literal orbidi-match-expanderuse applies to a single path element. - Simply giving the same response to all variants seems relatively straight-forward to add as a keyword option. However, that is (at least arguably) less optimal than redirecting to the canonical URL. Redirects open another can of worms, though, since
301 Moved Permanentlyhas issues for methods other thanGETandHEADand308 Permanent Redirectdoesn't have a straightforward fallback for older browsers. I would want to do a301 Moved PermanentlyforGETandHEADrequests and307 Temporary Redirectfor other methods, which RFC 7231 suggests is reasonable. The higher-level question is the trade-off between a simple API that "does the right thing" and configurability. - Building on that theme, there are some cases other than trailing
/support where a similar ability to handle variants on canonical URLs would be nice: for example, case-insensitivity. I can imagine possible extensions to thedispatch-rulesAPI to add a general concept of non-canonical URLs, and it is appealing from one perspective to avoid making trailing/support a baked-in special feature. On the other hand, though, there seems a risk of getting beyond the scope of this library.
- 主要言語
- Racket
- スター
- 100
- フォーク
- 48
- PR マージ指標
- 30日以内にマージされた PR はありません
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
racket/web-server のほかの issue
-
難易度 1/5 1時間未満 初心者へのやさしさ 70/100
racket/web-server#46 ·
-
難易度 4/5 3〜5日 初心者へのやさしさ 38/100
racket/web-server#141 ·
-
難易度 4/5 3〜5日 初心者へのやさしさ 45/100
racket/web-server#140 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 45/100
racket/web-server#135 ·
-
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
racket/web-server#131 · コメント 1 件 ·
racket/web-server の issue をすべて見る
似ている issue
-
HTML: <template> content is extracted as document text対応中かも @ryanmeowy が今日担当しました。 オープンbug html
難易度 1/5 1時間未満 初心者へのやさしさ 82/100
docling-project/docling#4714 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
First unknown-user login after boot is one scrypt run slower than a real user's wrong password対応中かも このイシューにリンクされたプルリクエストがオープン中、またはマージ済みです。 オープンarea: backend bug priority: low
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
snapotter-hq/SnapOtter#2254 ·
メンテナーはふだん 1 日以内に返信
-
[Chore] Remove dead AutogenV2 feature flag対応中かも @geeknishantkyeus が今日担当しました。 オープンbug triage
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
kyverno/kyverno#17936 · コメント 1 件 · リアクション 1 件 ·
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
Deepak3699/Ai_Mentor#244 ·
メンテナーはふだん 1 日以内に返信