`http.NewRequest (…)`를 사용하여 URL 인코딩 된 POST 요청을 만듭니다.


96

내 데이터를 application/x-www-form-urlencoded콘텐츠 유형 으로 보내는 API에 POST 요청을하고 싶습니다 . 요청 헤더를 관리해야하기 때문에이 http.NewRequest(method, urlStr string, body io.Reader)메서드를 사용하여 요청을 생성하고 있습니다. 이 POST 요청의 경우 데이터 쿼리를 URL에 추가하고 다음과 같이 본문을 비워 둡니다.

package main

import (
    "bytes"
    "fmt"
    "net/http"
    "net/url"
    "strconv"
)

func main() {
    apiUrl := "https://api.com"
    resource := "/user/"
    data := url.Values{}
    data.Set("name", "foo")
    data.Add("surname", "bar")

    u, _ := url.ParseRequestURI(apiUrl)
    u.Path = resource
    u.RawQuery = data.Encode()
    urlStr := fmt.Sprintf("%v", u) // "https://api.com/user/?name=foo&surname=bar"

    client := &http.Client{}
    r, _ := http.NewRequest("POST", urlStr, nil)
    r.Header.Add("Authorization", "auth_token=\"XXXXXXX\"")
    r.Header.Add("Content-Type", "application/x-www-form-urlencoded")
    r.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))

    resp, _ := client.Do(r)
    fmt.Println(resp.Status)
}

내가 응답하면 항상 400 BAD REQUEST. 문제가 내 요청에 의존하고 있으며 API가 내가 게시하는 페이로드를 이해하지 못한다고 생각합니다. 나는 같은 방법을 알고 Request.ParseForm있지만이 맥락에서 어떻게 사용하는지 잘 모르겠습니다. 추가 헤더가 누락되었을 수 있습니다 application/json. body매개 변수를 사용하여 페이로드를 유형 으로 보내는 더 좋은 방법이 있습니까?

답변:


184

URL로 인코딩 된 페이로드는 다음 을 구현하는 유형으로 메소드 의 body매개 변수에 제공되어야합니다.http.NewRequest(method, urlStr string, body io.Reader)io.Reader 인터페이스 .

샘플 코드를 기반으로 :

package main

import (
    "fmt"
    "net/http"
    "net/url"
    "strconv"
    "strings"
)

func main() {
    apiUrl := "https://api.com"
    resource := "/user/"
    data := url.Values{}
    data.Set("name", "foo")
    data.Set("surname", "bar")

    u, _ := url.ParseRequestURI(apiUrl)
    u.Path = resource
    urlStr := u.String() // "https://api.com/user/"

    client := &http.Client{}
    r, _ := http.NewRequest(http.MethodPost, urlStr, strings.NewReader(data.Encode())) // URL-encoded payload
    r.Header.Add("Authorization", "auth_token=\"XXXXXXX\"")
    r.Header.Add("Content-Type", "application/x-www-form-urlencoded")
    r.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))

    resp, _ := client.Do(r)
    fmt.Println(resp.Status)
}

resp.Status입니다 200 OK이런 식으로.


2
데이터를 보내지 않으려면 어떻게해야합니까 ?? `bytes.NewBufferString (data.Encode ())`대신 더미 데이터를 보내면 작동합니까?
Aditya Peshave 2015 년

빈 * Buffer를 보내려고합니다 : 예 : b주어진var b bytes.Buffer
Fernando Á.

4
이미 설정 한 Content-Lenght것처럼 헤더 를 설정할 필요가 없습니다 http.NewRequest.
dvdplm 2015

12
strings.NewReader(data.Encode())대신 (더 효율적) 사용할 수 있다고 생각 bytes.NewBufferString(data.Encode())합니다. 에서 * Reader가 NewReader을 (문자열) FUNC , 그것은 말한다 "NewReader가의에서 읽는 새로운 리더를 반환합니다. 그것은 bytes.NewBufferString과 유사하지만 읽기 전용보다 효율적이고있다."
Liyang Chen

1
data.Set대신 name및 둘 다에 사용해야합니다 . 동일한 키에 다른 값을 추가하는 대신 키 값을 설정합니다 . 작동하지만 슬라이스를 비울 필요가 없습니다 . surnamedata.Adddata.AddAddappend(v[key], value)
metalim
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.