gitea源码

url_test.go 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // Copyright 2023 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package httplib
  4. import (
  5. "context"
  6. "crypto/tls"
  7. "net/http"
  8. "testing"
  9. "code.gitea.io/gitea/modules/setting"
  10. "code.gitea.io/gitea/modules/test"
  11. "github.com/stretchr/testify/assert"
  12. )
  13. func TestIsRelativeURL(t *testing.T) {
  14. defer test.MockVariableValue(&setting.AppURL, "http://localhost:3000/sub/")()
  15. defer test.MockVariableValue(&setting.AppSubURL, "/sub")()
  16. rel := []string{
  17. "",
  18. "foo",
  19. "/",
  20. "/foo?k=%20#abc",
  21. }
  22. for _, s := range rel {
  23. assert.True(t, IsRelativeURL(s), "rel = %q", s)
  24. }
  25. abs := []string{
  26. "//",
  27. "\\\\",
  28. "/\\",
  29. "\\/",
  30. "mailto:a@b.com",
  31. "https://test.com",
  32. }
  33. for _, s := range abs {
  34. assert.False(t, IsRelativeURL(s), "abs = %q", s)
  35. }
  36. }
  37. func TestGuessCurrentHostURL(t *testing.T) {
  38. defer test.MockVariableValue(&setting.AppURL, "http://cfg-host/sub/")()
  39. defer test.MockVariableValue(&setting.AppSubURL, "/sub")()
  40. headersWithProto := http.Header{"X-Forwarded-Proto": {"https"}}
  41. t.Run("Legacy", func(t *testing.T) {
  42. defer test.MockVariableValue(&setting.PublicURLDetection, setting.PublicURLLegacy)()
  43. assert.Equal(t, "http://cfg-host", GuessCurrentHostURL(t.Context()))
  44. // legacy: "Host" is not used when there is no "X-Forwarded-Proto" header
  45. ctx := context.WithValue(t.Context(), RequestContextKey, &http.Request{Host: "req-host:3000"})
  46. assert.Equal(t, "http://cfg-host", GuessCurrentHostURL(ctx))
  47. // if "X-Forwarded-Proto" exists, then use it and "Host" header
  48. ctx = context.WithValue(t.Context(), RequestContextKey, &http.Request{Host: "req-host:3000", Header: headersWithProto})
  49. assert.Equal(t, "https://req-host:3000", GuessCurrentHostURL(ctx))
  50. })
  51. t.Run("Auto", func(t *testing.T) {
  52. defer test.MockVariableValue(&setting.PublicURLDetection, setting.PublicURLAuto)()
  53. assert.Equal(t, "http://cfg-host", GuessCurrentHostURL(t.Context()))
  54. // auto: always use "Host" header, the scheme is determined by "X-Forwarded-Proto" header, or TLS config if no "X-Forwarded-Proto" header
  55. ctx := context.WithValue(t.Context(), RequestContextKey, &http.Request{Host: "req-host:3000"})
  56. assert.Equal(t, "http://req-host:3000", GuessCurrentHostURL(ctx))
  57. ctx = context.WithValue(t.Context(), RequestContextKey, &http.Request{Host: "req-host", TLS: &tls.ConnectionState{}})
  58. assert.Equal(t, "https://req-host", GuessCurrentHostURL(ctx))
  59. ctx = context.WithValue(t.Context(), RequestContextKey, &http.Request{Host: "req-host:3000", Header: headersWithProto})
  60. assert.Equal(t, "https://req-host:3000", GuessCurrentHostURL(ctx))
  61. })
  62. }
  63. func TestMakeAbsoluteURL(t *testing.T) {
  64. defer test.MockVariableValue(&setting.Protocol, "http")()
  65. defer test.MockVariableValue(&setting.AppURL, "http://cfg-host/sub/")()
  66. defer test.MockVariableValue(&setting.AppSubURL, "/sub")()
  67. ctx := t.Context()
  68. assert.Equal(t, "http://cfg-host/sub/", MakeAbsoluteURL(ctx, ""))
  69. assert.Equal(t, "http://cfg-host/foo", MakeAbsoluteURL(ctx, "foo"))
  70. assert.Equal(t, "http://cfg-host/foo", MakeAbsoluteURL(ctx, "/foo"))
  71. assert.Equal(t, "http://other/foo", MakeAbsoluteURL(ctx, "http://other/foo"))
  72. ctx = context.WithValue(ctx, RequestContextKey, &http.Request{
  73. Host: "user-host",
  74. })
  75. assert.Equal(t, "http://cfg-host/foo", MakeAbsoluteURL(ctx, "/foo"))
  76. ctx = context.WithValue(ctx, RequestContextKey, &http.Request{
  77. Host: "user-host",
  78. Header: map[string][]string{
  79. "X-Forwarded-Host": {"forwarded-host"},
  80. },
  81. })
  82. assert.Equal(t, "http://cfg-host/foo", MakeAbsoluteURL(ctx, "/foo"))
  83. ctx = context.WithValue(ctx, RequestContextKey, &http.Request{
  84. Host: "user-host",
  85. Header: map[string][]string{
  86. "X-Forwarded-Host": {"forwarded-host"},
  87. "X-Forwarded-Proto": {"https"},
  88. },
  89. })
  90. assert.Equal(t, "https://user-host/foo", MakeAbsoluteURL(ctx, "/foo"))
  91. }
  92. func TestIsCurrentGiteaSiteURL(t *testing.T) {
  93. defer test.MockVariableValue(&setting.AppURL, "http://localhost:3000/sub/")()
  94. defer test.MockVariableValue(&setting.AppSubURL, "/sub")()
  95. ctx := t.Context()
  96. good := []string{
  97. "?key=val",
  98. "/sub",
  99. "/sub/",
  100. "/sub/foo",
  101. "/sub/foo/",
  102. "http://localhost:3000/sub?key=val",
  103. "http://localhost:3000/sub/",
  104. }
  105. for _, s := range good {
  106. assert.True(t, IsCurrentGiteaSiteURL(ctx, s), "good = %q", s)
  107. }
  108. bad := []string{
  109. ".",
  110. "foo",
  111. "/",
  112. "//",
  113. "\\\\",
  114. "/foo",
  115. "http://localhost:3000/sub/..",
  116. "http://localhost:3000/other",
  117. "http://other/",
  118. }
  119. for _, s := range bad {
  120. assert.False(t, IsCurrentGiteaSiteURL(ctx, s), "bad = %q", s)
  121. }
  122. setting.AppURL = "http://localhost:3000/"
  123. setting.AppSubURL = ""
  124. assert.False(t, IsCurrentGiteaSiteURL(ctx, "//"))
  125. assert.False(t, IsCurrentGiteaSiteURL(ctx, "\\\\"))
  126. assert.False(t, IsCurrentGiteaSiteURL(ctx, "http://localhost"))
  127. assert.True(t, IsCurrentGiteaSiteURL(ctx, "http://localhost:3000?key=val"))
  128. ctx = context.WithValue(ctx, RequestContextKey, &http.Request{
  129. Host: "user-host",
  130. Header: map[string][]string{
  131. "X-Forwarded-Host": {"forwarded-host"},
  132. "X-Forwarded-Proto": {"https"},
  133. },
  134. })
  135. assert.True(t, IsCurrentGiteaSiteURL(ctx, "http://localhost:3000"))
  136. assert.True(t, IsCurrentGiteaSiteURL(ctx, "https://user-host"))
  137. assert.False(t, IsCurrentGiteaSiteURL(ctx, "https://forwarded-host"))
  138. }
  139. func TestParseGiteaSiteURL(t *testing.T) {
  140. defer test.MockVariableValue(&setting.AppURL, "http://localhost:3000/sub/")()
  141. defer test.MockVariableValue(&setting.AppSubURL, "/sub")()
  142. ctx := t.Context()
  143. tests := []struct {
  144. url string
  145. exp *GiteaSiteURL
  146. }{
  147. {"http://localhost:3000/sub?k=v", &GiteaSiteURL{RoutePath: ""}},
  148. {"http://localhost:3000/sub/", &GiteaSiteURL{RoutePath: ""}},
  149. {"http://localhost:3000/sub/foo", &GiteaSiteURL{RoutePath: "/foo"}},
  150. {"http://localhost:3000/sub/foo/bar", &GiteaSiteURL{RoutePath: "/foo/bar", OwnerName: "foo", RepoName: "bar"}},
  151. {"http://localhost:3000/sub/foo/bar/", &GiteaSiteURL{RoutePath: "/foo/bar", OwnerName: "foo", RepoName: "bar"}},
  152. {"http://localhost:3000/sub/attachments/bar", &GiteaSiteURL{RoutePath: "/attachments/bar"}},
  153. {"http://localhost:3000/other", nil},
  154. {"http://other/", nil},
  155. }
  156. for _, test := range tests {
  157. su := ParseGiteaSiteURL(ctx, test.url)
  158. assert.Equal(t, test.exp, su, "URL = %s", test.url)
  159. }
  160. }