transport/http(feat): add redirector to forward request (#2074)

* add redirector to forward request

Co-authored-by: chenzhihui <chenzhihui@bilibili.com>
pull/2075/head
Tony Chen 3 years ago committed by GitHub
parent 5de1f081f6
commit 1b3529fd0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      transport/http/codec.go
  2. 18
      transport/http/redirect.go
  3. 23
      transport/http/redirect_test.go

@ -12,6 +12,12 @@ import (
// SupportPackageIsVersion1 These constants should not be referenced from any other code. // SupportPackageIsVersion1 These constants should not be referenced from any other code.
const SupportPackageIsVersion1 = true const SupportPackageIsVersion1 = true
// Redirector replies to the request with a redirect to url
// which may be a path relative to the request path.
type Redirector interface {
Redirect() (string, int)
}
// Request type net/http. // Request type net/http.
type Request = http.Request type Request = http.Request
@ -49,8 +55,12 @@ func DefaultRequestDecoder(r *http.Request, v interface{}) error {
// DefaultResponseEncoder encodes the object to the HTTP response. // DefaultResponseEncoder encodes the object to the HTTP response.
func DefaultResponseEncoder(w http.ResponseWriter, r *http.Request, v interface{}) error { func DefaultResponseEncoder(w http.ResponseWriter, r *http.Request, v interface{}) error {
if v == nil { if v == nil {
_, err := w.Write(nil) return nil
return err }
if rd, ok := v.(Redirector); ok {
url, code := rd.Redirect()
http.Redirect(w, r, url, code)
return nil
} }
codec, _ := CodecForRequest(r, "Accept") codec, _ := CodecForRequest(r, "Accept")
data, err := codec.Marshal(v) data, err := codec.Marshal(v)

@ -0,0 +1,18 @@
package http
type redirect struct {
URL string
Code int
}
func (r *redirect) Redirect() (string, int) {
return r.URL, r.Code
}
// NewRedirect new a redirect with url, which may be a path relative to the request path.
// The provided code should be in the 3xx range and is usually StatusMovedPermanently, StatusFound or StatusSeeOther.
// If the Content-Type header has not been set, Redirect sets it to "text/html; charset=utf-8" and writes a small HTML body.
// Setting the Content-Type header to any value, including nil, disables that behavior.
func NewRedirect(url string, code int) Redirector {
return &redirect{URL: url, Code: code}
}

@ -0,0 +1,23 @@
package http
import (
"net/http/httptest"
"testing"
)
func TestRedirect(t *testing.T) {
var (
redirectURL = "/redirect"
redirectCode = 302
)
r := httptest.NewRequest("POST", "/test", nil)
w := httptest.NewRecorder()
_ = DefaultResponseEncoder(w, r, NewRedirect(redirectURL, redirectCode))
if w.Code != redirectCode {
t.Fatalf("want %d but got %d", redirectCode, w.Code)
}
if v := w.Header().Get("Location"); v != redirectURL {
t.Fatalf("want %s but got %s", redirectURL, v)
}
}
Loading…
Cancel
Save