Golang中如何处理302重定向问题

Golang中如何处理302重定向问题 大家好,

我是 Golang 的新手。刚刚开始我的第一个 Go 项目。以下是我正在用 Go 实现的简要需求概述:

  1. 客户端将向 API 服务器发送授权请求。例如:http://api.xyz.com/v1/authorize?apiKey=“key”&redirect=“URL”
  2. 提交上述请求后,服务器将重定向到登录页面 - http://api.xyz.com/login
  3. 用户在此处使用凭据登录,验证通过后,将在 URL 查询参数中获得一个访问码。

请帮助 🙂

===================== 更新

我能够获取重定向的位置,但如何维持会话并在登录页面执行 POST 请求?示例请求体:

{
  "username": "joe"
  "password": "xxxxxxxx"
}

更多关于Golang中如何处理302重定向问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

请查看此链接了解如何在Go中使用会话的示例。

更多关于Golang中如何处理302重定向问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go中处理302重定向并维持会话可以通过http.Client配合cookie jar来实现。以下是完整的解决方案:

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "net/http/cookiejar"
    "net/url"
)

type LoginRequest struct {
    Username string `json:"username"`
    Password string `json:"password"`
}

func main() {
    // 创建带cookie jar的client以维持会话
    jar, _ := cookiejar.New(nil)
    client := &http.Client{
        Jar: jar,
        CheckRedirect: func(req *http.Request, via []*http.Request) error {
            // 允许重定向
            return nil
        },
    }

    // 第一步:发起授权请求
    authURL := "http://api.xyz.com/v1/authorize?apiKey=key&redirect=URL"
    resp, err := client.Get(authURL)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    // 检查是否为重定向
    if resp.StatusCode == http.StatusFound {
        location, err := resp.Location()
        if err != nil {
            panic(err)
        }
        fmt.Printf("重定向到: %s\n", location.String())
    }

    // 第二步:在登录页面执行POST请求
    loginData := LoginRequest{
        Username: "joe",
        Password: "xxxxxxxx",
    }

    jsonData, err := json.Marshal(loginData)
    if err != nil {
        panic(err)
    }

    loginURL := "http://api.xyz.com/login"
    req, err := http.NewRequest("POST", loginURL, bytes.NewBuffer(jsonData))
    if err != nil {
        panic(err)
    }

    req.Header.Set("Content-Type", "application/json")

    // 使用同一个client发送请求,cookies会自动处理
    loginResp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer loginResp.Body.Close()

    // 读取响应
    body, err := io.ReadAll(loginResp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Printf("登录响应状态: %d\n", loginResp.StatusCode)
    fmt.Printf("响应内容: %s\n", string(body))

    // 检查响应中是否包含访问码
    if loginResp.StatusCode == http.StatusOK {
        // 解析响应获取访问码
        var result map[string]interface{}
        json.Unmarshal(body, &result)
        if accessCode, exists := result["access_code"]; exists {
            fmt.Printf("获取到的访问码: %v\n", accessCode)
        }
    }
}

如果需要手动处理重定向和提取查询参数中的访问码:

func handleRedirectManually() {
    jar, _ := cookiejar.New(nil)
    client := &http.Client{
        Jar: jar,
        CheckRedirect: func(req *http.Request, via []*http.Request) error {
            // 返回此错误可阻止自动重定向,手动处理
            return http.ErrUseLastResponse
        },
    }

    // 发起请求
    resp, err := client.Get("http://api.xyz.com/v1/authorize?apiKey=key&redirect=URL")
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    if resp.StatusCode == http.StatusFound {
        location, _ := resp.Location()
        
        // 手动处理重定向后的URL
        parsedURL, _ := url.Parse(location.String())
        queryParams := parsedURL.Query()
        
        // 提取访问码
        if accessCode := queryParams.Get("access_code"); accessCode != "" {
            fmt.Printf("访问码: %s\n", accessCode)
        }
    }
}

关键点说明:

  • cookiejar 自动管理会话cookies
  • CheckRedirect 函数控制重定向行为
  • 使用同一个http.Client实例维持会话状态
  • 重定向后的请求会自动携带认证cookies
回到顶部