Fetch를 사용하여 x-www-form-urlencoded 요청을 게시하려면 어떻게합니까?


111

내 서버에 양식 인코딩 된 POST 매개 변수가 있습니다.

{
    'userName': 'test@gmail.com',
    'password': 'Password!',
    'grant_type': 'password'
}

다음과 같이 요청 (현재 매개 변수 없음)을 보냅니다.

var obj = {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
  },
};
fetch('https://example.com/login', obj)
  .then(function(res) {
    // Do stuff with result
  }); 

요청에 양식 인코딩 매개 변수를 포함하려면 어떻게해야합니까?


3
선택한 답변을 실제 정답으로 업데이트하십시오.
Albert Renshaw

답변:


-61

Form-Encoded POST 요청을 업로드하려면 FormData 객체를 사용하는 것이 좋습니다 .

예제 코드 :

var params = {
    userName: 'test@gmail.com',
    password: 'Password!',
    grant_type: 'password'
};

var formData = new FormData();

for (var k in params) {
    formData.append(k, params[k]);
}

var request = {
    method: 'POST',
    headers: headers,
    body: formData
};

fetch(url, request);

86
이것은 application / x-www-form-urlencoded가 아니지만 multipart / form-data
Haha TTpro

동의합니다.이 요청은 Content-Type으로 "application / x-www-form-urlencoded"가 아니라 "multipart / form-data"입니다.
b4stien

2
@Mzn - Google의 같은 서비스를 사용하는 경우 예를 들어 폐쇄 컴파일러 API를 , 서버는 받아 들일 것 application/x-www-form-urlencoded,하지 multipart/form-data.
Sphinxxx

12
이것이 어떻게 받아 들여지는 대답이 될 수 있습니까? 실제 질문에 대해서는
분명히

1
FormData 개체를 제출할 때 서버에서 추가 처리를 수행해야합니다. 기본적으로 파일 업로드처럼 일반 양식을 처리합니다. 일반 양식에 대한 FormData 객체의 장점은 무엇입니까?
MarsAndBack

272

다음과 같이 x-www-form-urlencoded 페이로드를 직접 구성해야합니다.

var details = {
    'userName': 'test@gmail.com',
    'password': 'Password!',
    'grant_type': 'password'
};

var formBody = [];
for (var property in details) {
  var encodedKey = encodeURIComponent(property);
  var encodedValue = encodeURIComponent(details[property]);
  formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");

fetch('https://example.com/login', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
  },
  body: formBody
})

참고 경우 사용했다 fetch대신 기본 반응의 A (충분히 현대) 브라우저에서, 당신은 대신 만들 수 URLSearchParams때문에, 그 본문으로 개체 및 사용을 표준 가져 오기는 상태 (가) 경우 있음 bodyA는 URLSearchParams개체를 다음과 같이 직렬화한다 application/x-www-form-urlencoded. 그러나 React Native 에서는URLSearchParams .


52
ES6 방법 :const formBody = Object.keys(details).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(details[key])).join('&');
에릭 Burel

URLSearchParams이 polyfill github.com/WebReflection/url-search-params은 기본 또는 이전 버전의 브라우저 반응을 위해 작동 할 수 있습니다.
bucabay

7
또 다른 유사한 방법 :const formBody = Object.entries(details).map(([key, value]) => encodeURIComponent(key) + '=' + encodeURIComponent(value)).join('&')
Flynn Hou

1
그것은 문자열로 JSON 배열 매개 변수를 변환
atulkhatri

제안 된 모든 방법을 시도했습니다. 내가 무엇을하든 fetch는 본문 주위에 원치 않는 따옴표를 문자열에 직접 삽입합니다. 이렇게하면 매개 변수가 구문 분석됩니다 (예 : ' "mykey': 'myvalue"'). 다른 사람은이 문제를 가지고있는 이들은 물론 단지 400 오류 (서버의 mykey가 아닌 "의 mykey 인식)을 초래하기 때문에 불가능 API를 호출하게 이해할 수.?.
데이브 멍 거는


49

사용하다 URLSearchParams

https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams

var data = new URLSearchParams();
data.append('userName', 'test@gmail.com');
data.append('password', 'Password');
data.append('grant_type', 'password');

이것은 php7이 FormData 인코딩을 올바르게 구문 분석하지 않았기 때문에 내가 의도 한 것을 만듭니다. 나는 그것이 PHP의 소년과 소녀들에게 더 많은 표를
얻길 바랍니다

6
-1; URLSearchParamsReact Native에는 존재하지 않습니다. ( github.com/facebook/react-native/issues/9596 참조 . )
Mark Amery

3
이제 React Native의 일부입니다. toString()요청을 전달하기 전에 데이터 를 호출해야합니다 body.
phatmann

RN이 구현했다고 말한 후에도 URLSearchParams여전히 문제가 있습니다. 사양에 따라 구현되었다고 생각하지 않으며 단순히 솔루션이 떨어지는 것도 아닙니다. 드롭을 시도 했지만 여전히 문제가 있는 경우 URLSearchParams '오류 : 구현되지 않음'을 읽어 보십시오 URLSearchParams.
zero298

14

방금이 일을했고 UrlSearchParams가 트릭을했습니다. 누군가에게 도움이된다면 여기에 내 코드가 있습니다.

import 'url-search-params-polyfill';
const userLogsInOptions = (username, password) => {



// const formData = new FormData();
  const formData = new URLSearchParams();
  formData.append('grant_type', 'password');
  formData.append('client_id', 'entrance-app');
  formData.append('username', username);
  formData.append('password', password);
  return (
    {
      method: 'POST',
      headers: {
        // "Content-Type": "application/json; charset=utf-8",
        "Content-Type": "application/x-www-form-urlencoded",
    },
      body: formData.toString(),
    json: true,
  }
  );
};


const getUserUnlockToken = async (username, password) => {
  const userLoginUri = `${scheme}://${host}/auth/realms/${realm}/protocol/openid-connect/token`;
  const response = await fetch(
    userLoginUri,
    userLogsInOptions(username, password),
  );
  const responseJson = await response.json();
  console.log('acces_token ', responseJson.access_token);
  if (responseJson.error) {
    console.error('error ', responseJson.error);
  }
  console.log('json ', responseJson);
  return responseJson.access_token;
};

5
*/ import this statement */
import qs from 'querystring'

fetch("*your url*", {
            method: 'POST',
            headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'},
            body: qs.stringify({ 
                username: "akshita",
                password: "123456",
            })
    }).then((response) => response.json())
      .then((responseData) => {
         alert(JSON.stringify(responseData))
    })

npm i querystring을 사용한 후- 잘 작동합니다.


5
var details = {
    'userName': 'test@gmail.com',
    'password': 'Password!',
    'grant_type': 'password'
};

var formBody = [];
for (var property in details) {
  var encodedKey = encodeURIComponent(property);
  var encodedValue = encodeURIComponent(details[property]);
  formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");

fetch('http://identity.azurewebsites.net' + '/token', {
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: formBody
})

나에게 매우 도움이되며 오류없이 작동합니다.

굴절 : https://gist.github.com/milon87/f391e54e64e32e1626235d4dc4d16dc8


3

그냥 사용

import  qs from "qs";
 let data = {
        'profileId': this.props.screenProps[0],
        'accountId': this.props.screenProps[1],
        'accessToken': this.props.screenProps[2],
        'itemId': this.itemId
    };
    return axios.post(METHOD_WALL_GET, qs.stringify(data))

1
이것은 정답으로 표시되어야합니다. 사용하기 쉽고 이상한 물건이 없습니다.
Augusto Gonzalez

3

jQuery를 사용 querystring하거나 페이로드를 수동으로 어셈블 할 필요가 없습니다 . URLSearchParams다음은 전체 요청 예제와 함께 가장 간결한 답변 중 하나입니다.

fetch('https://example.com/login', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: new URLSearchParams({
    'param': 'Some value',
    'another_param': 'Another value'
  })
})
  .then(res => {
    // Do stuff with the result
  });

예, 대신 Axios 또는 원하는 것을 사용할 수 있습니다. fetch .

PS URLSearchParams는 IE에서 지원되지 않습니다.


2

본체를 다음과 같이 설정하십시오.

var reqBody = "username="+username+"&password="+password+"&grant_type=password";

그때

fetch('url', {
      method: 'POST',
      headers: {
          //'Authorization': 'Bearer token',
          'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
      },
      body: reqBody
  }).then((response) => response.json())
      .then((responseData) => {
          console.log(JSON.stringify(responseData));
      }).catch(err=>{console.log(err)})

1

원래 예제 transformRequest에는 객체를 Form Encoded 데이터로 변환하는 함수가 있습니다.

수정 된 예제에서는 JSON.stringify객체를 JSON으로 변환하는 것으로 대체했습니다 .

두 경우 모두 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'있으므로 두 경우 모두 양식 인코딩 데이터를 전송 한다고 주장 합니다.

대신 양식 인코딩 기능을 사용하십시오 JSON.stringify.


다시 업데이트 :

첫 번째 fetch예에서는을 bodyJSON 값으로 설정합니다 .

이제 Form Encoded 버전을 만들었지 만을 body해당 값 으로 설정하는 대신 새 개체를 만들고 해당 개체의 속성으로 Form Encoded 데이터를 설정했습니다.

추가 개체를 만들지 마십시오. 귀하의 가치를에 할당하십시오 body.


안녕하세요 @Quentin. 나는 미래의 독자들에게 더 유용한 참고 자료로 만들기 위해 질문을 근본적으로 줄였습니다. 그렇게하면서 질문자의 원본 코드의 세부 사항과 버그를 참조하는 귀하의 답변을 완전히 무효화했습니다. 원하는 경우 내 편집을 되돌릴 수있는 권한이 있다고 생각합니다. 이론적으로는 답변을 무효화하는 편집을 할 수 없습니다. 이것이 제가 한 작업입니다.하지만 기꺼이 원할 경우에는 그렇게 생각합니다. 대신이 답변을 삭제하는 것이 좋습니다. IMO 질문은 Angular 코드 또는 이전의 실패한 시도없이 훨씬 더 좋습니다.
마크 Amery

1

JQuery를 사용하는 경우 이것도 작동합니다 ..

fetch(url, {
      method: 'POST', 
      body: $.param(data),
      headers:{
        'Content-Type': 'application/x-www-form-urlencoded'
      }
})

0

spec 에 따르면을 사용 encodeURIComponent하면 일치하는 쿼리 문자열이 제공되지 않습니다. 다음과 같이 설명합니다.

  1. 제어 이름과 값은 이스케이프됩니다. 공백 문자는로 대체 된+ 다음 예약 된 문자는 [RFC1738], 섹션 2.2에 설명 된대로 이스케이프됩니다. 영숫자가 아닌 문자는 %HH, 퍼센트 기호 및 문자의 ASCII 코드를 나타내는 두 개의 16 진수 로 대체됩니다 . 줄 바꿈은 "CR LF"쌍 (예 :)으로 표시됩니다 %0D%0A.
  2. 컨트롤 이름 / 값은 문서에 나타나는 순서대로 나열됩니다. 이름은로 값 =과 구분 되며 이름 / 값 쌍은로 구분됩니다 &.

문제는있다 encodeURIComponent할 공간을 인코딩 %20하지 +.

양식 본문은 encodeURIComponent다른 답변에 표시된 방법 의 변형을 사용하여 코딩되어야합니다 .

const formUrlEncode = str => {
  return str.replace(/[^\d\w]/g, char => {
    return char === " " 
      ? "+" 
      : encodeURIComponent(char);
  })
}

const data = {foo: "bar߃©˙∑  baz", boom: "pow"};

const dataPairs = Object.keys(data).map( key => {
  const val = data[key];
  return (formUrlEncode(key) + "=" + formUrlEncode(val));
}).join("&");

// dataPairs is "foo=bar%C3%9F%C6%92%C2%A9%CB%99%E2%88%91++baz&boom=pow"

0

http 요청을 전송하고 차단 요청을 공식화 하기 쉬운 react-native-easy-app 을 사용할 수 있습니다 .

import { XHttp } from 'react-native-easy-app';

* Synchronous request
const params = {name:'rufeng',age:20}
const response = await XHttp().url(url).param(params).formEncoded().execute('GET');
const {success, json, message, status} = response;


* Asynchronous requests
XHttp().url(url).param(params).formEncoded().get((success, json, message, status)=>{
    if (success){
       this.setState({content: JSON.stringify(json)});
    } else {
       showToast(msg);
    }
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.