Skip to content

Commit

Permalink
addd redirect support for client
Browse files Browse the repository at this point in the history
  • Loading branch information
ninedraft committed Aug 2, 2022
1 parent fa3b974 commit 25d8d63
Showing 1 changed file with 53 additions and 4 deletions.
57 changes: 53 additions & 4 deletions gemax/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package gemax
import (
"context"
"crypto/tls"
"errors"
"fmt"
"io"
"net"
Expand All @@ -20,19 +21,67 @@ import (
type Client struct {
MaxResponseSize int64
Dial func(ctx context.Context, host string, cfg *tls.Config) (net.Conn, error)
Redirect func(ctx context.Context, req *urlpkg.URL, prev []RedirectedRequest) error
once sync.Once
}

var ErrTooManyRedirects = errors.New("too many redirects")

func (client *Client) checkRedirect(ctx context.Context, req *urlpkg.URL, prev []RedirectedRequest) error {
if client.Redirect != nil {
return client.Redirect(ctx, req, prev)
}
return defaultRedirect(ctx, req, prev)
}

func defaultRedirect(_ context.Context, _ *urlpkg.URL, prev []RedirectedRequest) error {
const max = 10
if len(prev) < max {
return nil
}
return ErrTooManyRedirects
}

type RedirectedRequest struct {
Req *urlpkg.URL
Response *Response
}

const readerBufSize = 16 << 10

// Fetch gemini resource.
func (client *Client) Fetch(ctx context.Context, url string) (*Response, error) {
client.init()
var u, errParseURL = urlpkg.Parse(url)
if errParseURL != nil {
return nil, fmt.Errorf("parsing URL: %w", errParseURL)
var redirects []RedirectedRequest
for {
var u, errParseURL = urlpkg.Parse(url)
if errParseURL != nil {
return nil, fmt.Errorf("parsing URL: %w", errParseURL)
}
if err := client.checkRedirect(ctx, u, redirects); err != nil {
return nil, fmt.Errorf("redirect: %w", err)
}
resp, errFetch := client.fetch(ctx, url, u)
if errFetch != nil {
return resp, errFetch
}
if !isRedirect(resp.Status) {
return resp, nil
}
resp.Close()
redirects = append(redirects, RedirectedRequest{
Req: u,
Response: resp,
})
url = resp.Meta
}
}

func isRedirect(code status.Code) bool {
return code == status.Redirect || code == status.RedirectPermanent
}

func (client *Client) fetch(ctx context.Context, origURL string, u *urlpkg.URL) (*Response, error) {
var host = u.Host
if strings.LastIndexByte(host, ':') < 0 {
host += ":1965"
Expand All @@ -51,7 +100,7 @@ func (client *Client) Fetch(ctx context.Context, url string) (*Response, error)
}
ctxConnDeadline(ctx, conn)

var _, errWrite = io.WriteString(conn, url+"\r\n")
var _, errWrite = io.WriteString(conn, origURL+"\r\n")
if errWrite != nil {
return nil, fmt.Errorf("sending request: %w", errWrite)
}
Expand Down

0 comments on commit 25d8d63

Please sign in to comment.