ฉันจะโพสต์ข้อมูลเป็นข้อมูลแบบฟอร์มแทนที่จะเป็นเพย์โหลดคำขอได้อย่างไร


523

ในรหัสด้านล่างนี้$httpวิธีAngularJS เรียก URL และส่งวัตถุ xsrf เป็น "ขอให้จัดทำข้อมูล" (ตามที่อธิบายไว้ในแท็บเครือข่ายดีบักเกอร์ Chrome) $.ajaxวิธีการjQuery ทำการโทรแบบเดียวกัน แต่ส่ง xsrf เป็น "Data Form"

ฉันจะทำให้ AngularJS ส่ง xsrf เป็นข้อมูลแบบฟอร์มแทนที่จะเป็นเพย์โหลดคำขอได้อย่างไร

var url = 'http://somewhere.com/';
var xsrf = {fkey: 'xsrf key'};

$http({
    method: 'POST',
    url: url,
    data: xsrf
}).success(function () {});

$.ajax({
    type: 'POST',
    url: url,
    data: xsrf,
    dataType: 'json',
    success: function() {}
});

1
นี่เป็นคำถามที่มีประโยชน์มาก มันทำให้ฉันสามารถส่งเพย์โหลดเป็นสตริง (โดยการเปลี่ยนประเภทเนื้อหา) ซึ่งป้องกันไม่ให้ฉันต้องจัดการกับ OPTIONS ก่อน POST / GET
earthmeLon

ฉันมีคำถามเดียวกันหลังจากฉันขอ URL แล้ว แต่ฉันไม่สามารถรับพารามิเตอร์ที่ฉันส่งได้
黄伟杰

คำตอบ:


614

ต้องเพิ่มบรรทัดต่อไปนี้ลงในออบเจ็กต์ $ http ที่ผ่าน:

headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}

และข้อมูลที่ส่งผ่านควรแปลงเป็นสตริงที่เข้ารหัส URL:

> $.param({fkey: "key"})
'fkey=key'

ดังนั้นคุณมีสิ่งที่ชอบ:

$http({
    method: 'POST',
    url: url,
    data: $.param({fkey: "key"}),
    headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
})

จาก: https://groups.google.com/forum/#!msg/angular/5nAedJ1LyO0/4Vj_72EZcDsJ

UPDATE

หากต้องการใช้บริการใหม่ที่เพิ่มเข้ามาด้วย AngularJS V1.4 โปรดดู


3
มีวิธีการเข้ารหัส json> url ของข้อมูลที่จะเกิดขึ้นโดยอัตโนมัติหรือเพื่อระบุสิ่งนี้เกิดขึ้นสำหรับทุกวิธีการ POST หรือ PUT?
Dogoku

51
+1 @mjibson สำหรับฉันแม้แต่ผ่านส่วนหัวก็ไม่ทำงานจนกว่าฉันจะเห็นคำตอบของคุณที่มีนี้: var xsrf = $.param({fkey: "key"});นั่นโง่ทำไมทำมุมภายในไม่สามารถทำภายใน
naikus

12
ในการติดตามพฤติกรรมเริ่มต้นของ $ .ajax ให้ใกล้ชิดยิ่งขึ้นชุดอักขระควรถูกระบุในส่วนหัวของชนิดเนื้อหา -headers: {Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
Imre

25
แทนที่จะใช้ฟังก์ชั่นพารามิเตอร์ของ jQuery เพียงแค่ตั้งค่าคุณสมบัติพารามิเตอร์บนคำขอ $ http และจะทำสิ่งที่วิธีการ jQuery.param ทำตราบเท่าที่ส่วนหัวของประเภทเนื้อหาคือ 'application / x-www-form-urlencoded' - stackoverflow .com / คำถาม / 18967307 / …
spig

13
@spig ใช่มันจะทำสิ่งที่ jQuery.param ทำ แต่ถ้าคุณใช้คุณสมบัติ params คุณสมบัติของคุณจะถูกเข้ารหัสเป็นส่วนหนึ่งของ URL คำขอแทนที่จะเป็นเนื้อหา - แม้ว่าคุณจะได้ระบุแอปพลิเคชัน / x-www- ส่วนหัวแบบฟอร์ม urlencoded
เตียน

194

หากคุณไม่ต้องการใช้ jQuery ในโซลูชันคุณสามารถลองได้ ทางออกจากที่นี่ https://stackoverflow.com/a/1714899/1784301

$http({
    method: 'POST',
    url: url,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    transformRequest: function(obj) {
        var str = [];
        for(var p in obj)
        str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
        return str.join("&");
    },
    data: xsrf
}).success(function () {});

7
วิธีนี้ใช้ได้กับฉันในเชิงมุม 1.2.x และฉันคิดว่ามันเป็นคำตอบที่ดีที่สุดเพราะมันสง่างามมันใช้งานได้ในแกนมุมและไม่ต้องพึ่งพาไลบรารีภายนอกใด ๆ เช่น jQuery
gregtczap

2
ฉันเจอปัญหาเมื่อใช้วิธีนี้ภายใน $ action action ข้อมูลในแบบฟอร์มยังรวมถึงฟังก์ชั่นสำหรับ $ get, $ save และอื่น ๆ โซลูชันคือการแก้ไขforคำสั่งเล็กน้อยเพื่อใช้angular.forEachแทน
แอนโทนี่

10
โปรดทราบว่าในทางตรงกันข้ามกับ $ .param () วิธีนี้จะไม่ทำงานซ้ำในอาร์เรย์ / วัตถุ
MazeChaZer

1
ฉันต้องการตรวจสอบว่าobj[p]ไม่ได้เป็นโมฆะหรือไม่ได้กำหนด มิฉะนั้นคุณจะสิ้นสุดการส่งสตริง "null" หรือ "undefined" เป็นค่า
Tamir

1
ฉันไม่เข้าใจtransformRequest: function(obj)เนื่องจาก obj ไม่ได้กำหนดเราคิดว่าจะส่งผ่าน xsrf หรือไม่ ชอบtransformRequest: function(xsrf)
Akshay ทารุ

92

ความสับสนอย่างต่อเนื่องเกี่ยวกับปัญหานี้เป็นแรงบันดาลใจให้ฉันเขียนโพสต์บล็อกเกี่ยวกับเรื่องนี้ โซลูชันที่ฉันเสนอในโพสต์นี้ดีกว่าโซลูชันที่ได้รับคะแนนสูงสุดในปัจจุบันของคุณเพราะไม่ได้ จำกัด ให้คุณกำหนดวัตถุข้อมูลของคุณสำหรับการเรียกใช้บริการ $ http; เช่นกับโซลูชันของฉันคุณสามารถส่งต่อวัตถุข้อมูลจริงไปที่ $ http.post () และยังคงได้ผลลัพธ์ตามที่ต้องการ

คำตอบที่ได้รับคะแนนสูงสุดนั้นขึ้นอยู่กับการรวม jQuery แบบเต็มในหน้าสำหรับฟังก์ชั่น $ .param () ในขณะที่คำตอบของฉันคือ jQuery ผู้ไม่เชื่อเรื่องพระเจ้าพร้อม AngularJS บริสุทธิ์

http://victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax/

หวังว่านี่จะช่วยได้


10
+1 สำหรับบล็อกรายละเอียด แต่ความจริงที่ว่ามีความจำเป็นสำหรับการนี้เป็นที่น่ากลัว ...
Iwein

4
ใช่อาจจะน่ากลัวในสองระดับคือ 1) ที่ AngularJS ตัดสินใจที่จะคว่ำพฤตินัย (แม้ว่าจะเข้าใจผิดที่ยอมรับ) มาตรฐานและ 2) PHP (และผู้ที่รู้สิ่งที่ภาษาด้านเซิร์ฟเวอร์อื่น ๆ ) อย่างใดไม่ได้ตรวจสอบ application / JSON โดยอัตโนมัติ อินพุต : P
Ezekiel Victor

เป็นไปได้ไหมที่ angularjs จะปรับให้เข้ากับประเภทเนื้อหาและเข้ารหัสตามโดยอัตโนมัติ? มองเห็นล่วงหน้าไหม
เลิก

4
ฉัน (เหมือนคนอื่น ๆ ) เจอเรื่องนี้ที่แบ็กเอนด์ของฉันASP.NETไม่ได้ 'สนับสนุน' สิ่งนี้ หากคุณไม่ต้องการเปลี่ยนพฤติกรรมของ AngularJS (ซึ่งฉันทำไม่ได้เพราะ API ของฉันคืน JSON แล้วทำไมมันไม่ยอมรับ JSON ด้วยเช่นกันมันมีความยืดหยุ่นมากกว่าข้อมูลแบบฟอร์ม) คุณสามารถอ่านได้จากRequest.InputStreamนั้นจัดการได้ทุกทาง คุณต้องการมัน. (ฉันเลือกที่จะลดความมันลงdynamicเพื่อความสะดวกในการใช้งาน)
Aidiakapi

2
Downvoted เพราะนี้ไม่ได้เป็นคำตอบอยู่ในตัวเอง คำตอบที่ดีไม่เพียง แต่เชื่อมโยงกับที่อื่น จากวิธีการตอบ : "อ้างอิงส่วนที่เกี่ยวข้องที่สุดของลิงค์สำคัญเสมอในกรณีที่ไซต์เป้าหมายไม่สามารถเข้าถึงหรือออฟไลน์ถาวร"
James

83

ฉันใช้คำตอบอื่น ๆ สองสามข้อและทำให้บางสิ่งบางอย่างสะอาด.config()สะอ้านวางสายนี้ไว้ที่ส่วนท้ายของ angular.module ใน app.js ของคุณ:

.config(['$httpProvider', function ($httpProvider) {
  // Intercept POST requests, convert to standard form encoding
  $httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
  $httpProvider.defaults.transformRequest.unshift(function (data, headersGetter) {
    var key, result = [];

    if (typeof data === "string")
      return data;

    for (key in data) {
      if (data.hasOwnProperty(key))
        result.push(encodeURIComponent(key) + "=" + encodeURIComponent(data[key]));
    }
    return result.join("&");
  });
}]);

1
ใช้งานได้อย่างมีเสน่ห์แม้ว่าจะผนวกเข้ากับการกำหนดทรัพยากร
Kai Mattern

3
ยังใช้ความระมัดระวังเพื่อunshift()ให้การเปลี่ยนแปลงอื่น ๆ ยังคงไม่ถูกรบกวน การทำงานที่ดี.
Aditya MP

2
ที่สมบูรณ์แบบ! ทำงานได้ดีสำหรับฉัน! เชิงมุมที่น่าเศร้าไม่สนับสนุนสิ่งนี้
spierala

2
คำตอบนี้ควรเป็นคำที่ถูกต้องที่ด้านบนสุดคำตอบอื่น ๆ ผิดขอบคุณเพื่อน !!
Jose Ignacio Hita

2
วิธีการเกี่ยวกับการเข้ารหัสซ้ำ?
Petah

58

ในฐานะของ AngularJS v1.4.0 มี$httpParamSerializerบริการในตัวที่แปลงวัตถุใด ๆ ให้เป็นส่วนหนึ่งของคำขอ HTTP ตามกฎที่ระบุไว้ในหน้าเอกสารหน้าเอกสาร

มันสามารถใช้เช่นนี้:

$http.post('http://example.com', $httpParamSerializer(formDataObj)).
    success(function(data){/* response status 200-299 */}).
    error(function(data){/* response status 400-999 */});

โปรดจำไว้ว่าสำหรับการโพสต์แบบฟอร์มที่ถูกต้องContent-Typeส่วนหัวจะต้องเปลี่ยน หากต้องการทำเช่นนี้ทั่วโลกสำหรับคำขอ POST ทั้งหมดคุณสามารถใช้รหัสนี้ (นำมาจากคำตอบครึ่งหนึ่งของ Albireo):

$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";

หากต้องการทำสิ่งนี้เฉพาะกับโพสต์ปัจจุบันheadersคุณสมบัติของคำขอวัตถุต้องได้รับการแก้ไข:

var req = {
 method: 'POST',
 url: 'http://example.com',
 headers: {
   'Content-Type': 'application/x-www-form-urlencoded'
 },
 data: $httpParamSerializer(formDataObj)
};

$http(req);

เราจะทำเช่นเดียวกันกับโรงงานทรัพยากร $ แบบกำหนดเองได้อย่างไร
stilllife

หมายเหตุ: ฉันอัพเกรดแอพจาก Angular 1.3 เป็น 1.5 มันเปลี่ยนส่วนหัวใน transformRequest ด้วยเหตุผลบางอย่างวิธีการข้างต้นไม่ได้ผลสำหรับฉัน Angular เพิ่มเครื่องหมายคำพูดคู่รอบสตริงที่เข้ารหัส URL transformRequest: $httpParamSerializer, data: formDataObjแก้ไขได้ด้วย ขอบคุณสำหรับการแก้ปัญหา
PhiLho

24

คุณสามารถกำหนดพฤติกรรมทั่วโลก:

$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";

ดังนั้นคุณไม่จำเป็นต้องกำหนดใหม่ทุกครั้ง:

$http.post("/handle/post", {
    foo: "FOO",
    bar: "BAR"
}).success(function (data, status, headers, config) {
    // TODO
}).error(function (data, status, headers, config) {
    // TODO
});

46
ตัวอย่างของคุณผิดมาก ... สิ่งที่คุณกำลังแก้ไขคือส่วนหัว ข้อมูลจะยังคงถูกเข้ารหัสด้วย JSON และอ่านไม่ได้โดยเซิร์ฟเวอร์เก่าที่ไม่สามารถอ่าน JSON ได้
alexk

victorblog.com/2012/12/12/… - นี่คือตัวอย่างที่ดีที่คุณแทนที่ส่วนหัวเริ่มต้น $ http รวมทั้งแปลงวัตถุให้เป็นข้อมูลในแบบฟอร์มที่ทำให้เป็นอนุกรม
Federico

20

คุณสามารถทำให้โค้ดที่รับ POST ตอบสนองต่อข้อมูลแอปพลิเคชัน / json สำหรับ PHP ฉันเพิ่มโค้ดด้านล่างทำให้ฉันสามารถโพสต์ได้ทั้งในรูปแบบการเข้ารหัสหรือ JSON

//handles JSON posted arguments and stuffs them into $_POST
//angular's $http makes JSON posts (not normal "form encoded")
$content_type_args = explode(';', $_SERVER['CONTENT_TYPE']); //parse content_type string
if ($content_type_args[0] == 'application/json')
  $_POST = json_decode(file_get_contents('php://input'),true);

//now continue to reference $_POST vars as usual

นี่เป็นหนึ่งในตัวอย่างที่ดีของการแก้ไขฝั่งเซิร์ฟเวอร์เนื่องจากปัญหาที่แท้จริงของปัญหานี้อยู่บนฝั่งเซิร์ฟเวอร์ API .. bravo
Vignesh

16

คำตอบเหล่านี้ดูเหมือน overkill บ้าบางครั้งง่ายดีกว่า:

$http.post(loginUrl, "userName=" + encodeURIComponent(email) +
                     "&password=" + encodeURIComponent(password) +
                     "&grant_type=password"
).success(function (data) {
//...

1
สำหรับฉันฉันยังคงมีการระบุส่วนหัวและตั้งค่าให้Content-Type application/x-www-form-urlencoded
Victor Ramos

9

คุณสามารถลองด้วยวิธีการแก้ปัญหาด้านล่าง

$http({
        method: 'POST',
        url: url-post,
        data: data-post-object-json,
        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
        transformRequest: function(obj) {
            var str = [];
            for (var key in obj) {
                if (obj[key] instanceof Array) {
                    for(var idx in obj[key]){
                        var subObj = obj[key][idx];
                        for(var subKey in subObj){
                            str.push(encodeURIComponent(key) + "[" + idx + "][" + encodeURIComponent(subKey) + "]=" + encodeURIComponent(subObj[subKey]));
                        }
                    }
                }
                else {
                    str.push(encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]));
                }
            }
            return str.join("&");
        }
    }).success(function(response) {
          /* Do something */
        });

8

สร้างบริการอะแดปเตอร์สำหรับโพสต์:

services.service('Http', function ($http) {

    var self = this

    this.post = function (url, data) {
        return $http({
            method: 'POST',
            url: url,
            data: $.param(data),
            headers: {'Content-Type': 'application/x-www-form-urlencoded'}
        })
    }

}) 

ใช้ในตัวควบคุมของคุณหรืออะไรก็ตาม:

ctrls.controller('PersonCtrl', function (Http /* our service */) {
    var self = this
    self.user = {name: "Ozgur", eMail: null}

    self.register = function () {
        Http.post('/user/register', self.user).then(function (r) {
            //response
            console.log(r)
        })
    }

})

$ .param เฉพาะใน jquery abi jsfiddle.net/4n9fao9q/27 $ httpParamSerializer เทียบเท่า Angularjs
Dexter

7

- มีการกวดวิชาที่ดีจริงๆที่จะไปมากกว่านี้และสิ่งอื่น ๆ ที่เกี่ยวข้องAngularJS Way:

โดยทั่วไปคุณต้องตั้งค่าส่วนหัวของคำขอ POST เพื่อระบุว่าคุณกำลังส่งข้อมูลแบบฟอร์มเป็นสตริงที่เข้ารหัส URL และตั้งค่าข้อมูลที่จะส่งในรูปแบบเดียวกัน

$http({
  method  : 'POST',
  url     : 'url',
  data    : $.param(xsrf),  // pass in data as strings
  headers : { 'Content-Type': 'application/x-www-form-urlencoded' }  // set the headers so angular passing info as form data (not request payload)
});

โปรดทราบว่าฟังก์ชั่นตัวช่วย param () ของ jQuery ใช้ที่นี่เพื่อจัดลำดับข้อมูลเป็นสตริง แต่คุณสามารถทำได้ด้วยตนเองเช่นกันหากไม่ได้ใช้ jQuery


1
ผู้ดำเนินรายการเพียงแค่ลบคำตอบก่อนหน้าของฉันเพราะฉันไม่ได้ให้รายละเอียดของการใช้งานจริงที่กล่าวถึงในลิงค์ คงจะดีกว่าถ้าพวกเขาขอให้ฉันก่อนที่จะให้รายละเอียดเพิ่มเติมแทนที่จะลบมันเพราะฉันได้แก้ไขคำตอบของฉันเพื่อให้รายละเอียดตามที่เห็นในคำตอบนี้!
robinmitra

การ$.paramทำเวทย์มนตร์ โซลูชั่นที่สมบูรณ์แบบสำหรับผู้ที่มีแอพที่ใช้ jQuery + AngularJS
dashtinejad


4

สำหรับผู้ใช้ Symfony2:

หากคุณไม่ต้องการเปลี่ยนแปลงอะไรในจาวาสคริปต์ของคุณเพื่อให้ใช้งานได้คุณสามารถแก้ไขสิ่งเหล่านี้ได้ในแอป symfony ของคุณ:

สร้างคลาสที่ขยายคลาส Symfony \ Component \ HttpFoundation \ Request:

<?php

namespace Acme\Test\MyRequest;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\ParameterBag;

class MyRequest extends Request{


/**
* Override and extend the createFromGlobals function.
* 
* 
*
* @return Request A new request
*
* @api
*/
public static function createFromGlobals()
{
  // Get what we would get from the parent
  $request = parent::createFromGlobals();

  // Add the handling for 'application/json' content type.
  if(0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/json')){

    // The json is in the content
    $cont = $request->getContent();

    $json = json_decode($cont);

    // ParameterBag must be an Array.
    if(is_object($json)) {
      $json = (array) $json;
  }
  $request->request = new ParameterBag($json);

}

return $request;

}

}

ตอนนี้ใช้คลาสของคุณใน app_dev.php (หรือไฟล์ดัชนีใด ๆ ที่คุณใช้)

// web/app_dev.php

$kernel = new AppKernel('dev', true);
// $kernel->loadClassCache();
$request = ForumBundleRequest::createFromGlobals();

// use your class instead
// $request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);

นี่เป็นประโยชน์กับฉันจริงๆ createFromGlobals ใหม่ทำงานได้อย่างสมบูรณ์แบบในขณะนี้ ฉันไม่รู้ว่าทำไมคุณถึงได้รับการโหวต แต่ฉันลบมันออก
Richard

3

เพียงแค่ตั้งค่าประเภทเนื้อหาไม่เพียงพอ url เข้ารหัสข้อมูลในแบบฟอร์มก่อนส่ง $http.post(url, jQuery.param(data))


3

ขณะนี้ฉันใช้โซลูชันต่อไปนี้ที่ฉันพบในกลุ่ม Google AngularJS

$ http
.post ('/ echo / json /', 'json =' + encodeURIComponent (angular.toJson (ข้อมูล)), {
    ส่วนหัว: {
        'ชนิดเนื้อหา': 'application / x-www ฟอร์ม urlencoded; charset = UTF-8'
    }
}). ความสำเร็จ (ฟังก์ชั่น (ข้อมูล) {
    $ scope.data = data;
});

โปรดทราบว่าหากคุณใช้ PHP คุณจะต้องใช้ส่วนประกอบเช่น Symfony 2 HTTP Request::createFromGlobals()เพื่ออ่านสิ่งนี้เนื่องจาก $ _POST จะไม่โหลดโดยอัตโนมัติ


2

AngularJS ทำถูกต้องเนื่องจากทำเนื้อหาประเภทต่อไปนี้ภายในส่วนหัว http- คำขอ:

Content-Type: application/json

ถ้าคุณจะไปด้วย php เหมือนผมหรือแม้กระทั่งกับ Symfony2 คุณสามารถขยายการทำงานร่วมกันของเซิร์ฟเวอร์สำหรับมาตรฐาน JSON เช่นอธิบายไว้ที่นี่: http://silex.sensiolabs.org/doc/cookbook/json_request_body.html

วิธี Symfony2 (เช่นภายใน DefaultController ของคุณ):

$request = $this->getRequest();
if (0 === strpos($request->headers->get('Content-Type'), 'application/json')) {
    $data = json_decode($request->getContent(), true);
    $request->request->replace(is_array($data) ? $data : array());
}
var_dump($request->request->all());

ข้อดีคือคุณไม่จำเป็นต้องใช้ jQuery param และคุณสามารถใช้ AngularJS เป็นวิธีดั้งเดิมในการดำเนินการตามคำขอ


2

คำตอบที่สมบูรณ์ (ตั้งแต่เชิงมุม 1.4) คุณต้องรวมการพึ่งพา $ httpParamSerializer

var res = $resource(serverUrl + 'Token', { }, {
                save: { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
            });

            res.save({ }, $httpParamSerializer({ param1: 'sdsd', param2: 'sdsd' }), function (response) {

            }, function (error) { 

            });

1

ในการกำหนดค่าแอปของคุณ -

$httpProvider.defaults.transformRequest = function (data) {
        if (data === undefined)
            return data;
        var clonedData = $.extend(true, {}, data);
        for (var property in clonedData)
            if (property.substr(0, 1) == '$')
                delete clonedData[property];

        return $.param(clonedData);
    };

ด้วยคำขอทรัพยากรของคุณ -

 headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            }

0

นี่ไม่ใช่คำตอบโดยตรง แต่เป็นทิศทางการออกแบบที่แตกต่างกันเล็กน้อย:

อย่าโพสต์ข้อมูลเป็นรูปแบบ แต่เป็นวัตถุ JSON ที่จะแมปโดยตรงกับวัตถุฝั่งเซิร์ฟเวอร์หรือใช้ตัวแปรเส้นทางสไตล์ REST

ตอนนี้ฉันรู้ว่าตัวเลือกไม่เหมาะสำหรับคุณเนื่องจากคุณพยายามส่งคีย์ XSRF การแม็พกับตัวแปรพา ธ แบบนี้เป็นการออกแบบที่แย่มาก:

http://www.someexample.com/xsrf/{xsrfKey}

เพราะโดยธรรมชาติที่คุณจะต้องการที่จะผ่านที่สำคัญ XSRF ไปยังเส้นทางอื่น ๆ ด้วย/login,/book-appointmentฯลฯ และคุณไม่ต้องการยุ่ง URL สวยของคุณ

การเพิ่มลงในฟิลด์วัตถุที่น่าสนใจก็ไม่เหมาะสมเช่นกันเพราะตอนนี้บนแต่ละวัตถุ json ที่คุณส่งไปยังเซิร์ฟเวอร์คุณต้องเพิ่มฟิลด์

{
  appointmentId : 23,
  name : 'Joe Citizen',
  xsrf : '...'
}

แน่นอนคุณไม่ต้องการเพิ่มเขตข้อมูลอื่นในคลาสฝั่งเซิร์ฟเวอร์ของคุณซึ่งไม่มีการเชื่อมโยงความหมายโดยตรงกับวัตถุโดเมน

ในความคิดของฉันวิธีที่ดีที่สุดในการส่งคีย์ xsrf ของคุณคือผ่านส่วนหัว HTTP ไลบรารีเฟรมเวิร์กเว็บการป้องกันเซิร์ฟเวอร์ xsrf จำนวนมากสนับสนุนสิ่งนี้ ตัวอย่างเช่นใน Java Spring คุณสามารถส่งผ่านโดยใช้X-CSRF-TOKENส่วนหัวส่วนหัว

ความสามารถที่ยอดเยี่ยมของ Angular ในการเชื่อมโยงวัตถุ JS ไปยังวัตถุ UI หมายความว่าเราสามารถกำจัดการฝึกการโพสต์ฟอร์มทั้งหมดเข้าด้วยกันและโพสต์ JSON แทน JSON สามารถถูกทำให้เป็นอนุกรมในวัตถุฝั่งเซิร์ฟเวอร์และสนับสนุนโครงสร้างข้อมูลที่ซับซ้อนเช่นแผนที่, อาร์เรย์, วัตถุที่ซ้อนกันและอื่น ๆ

คุณจะทำอย่างไรโพสต์อาร์เรย์ในบรรจุรูปแบบ? อาจจะเป็นเช่นนี้:

shopLocation=downtown&daysOpen=Monday&daysOpen=Tuesday&daysOpen=Wednesday

หรือสิ่งนี้:

shopLocation=downtwon&daysOpen=Monday,Tuesday,Wednesday

ทั้งมีการออกแบบที่น่าสงสาร ..


0

นี่คือสิ่งที่ฉันทำเพื่อความต้องการของฉันที่ฉันต้องการส่งข้อมูลการเข้าสู่ระบบไปยัง API เป็นข้อมูลแบบฟอร์มและวัตถุ Javascript (userData) จะถูกแปลงโดยอัตโนมัติเป็นข้อมูลที่เข้ารหัส URL

        var deferred = $q.defer();
        $http({
            method: 'POST',
            url: apiserver + '/authenticate',
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            transformRequest: function (obj) {
                var str = [];
                for (var p in obj)
                    str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
                return str.join("&");
            },
            data: userData
        }).success(function (response) {
            //logics
            deferred.resolve(response);
        }).error(function (err, status) {
           deferred.reject(err);
        });

นี่คือข้อมูลผู้ใช้ของฉัน

var userData = {
                grant_type: 'password',
                username: loginData.userName,
                password: loginData.password
            }

-1

เพียงบางที่คุณต้องเปลี่ยนคือการใช้ "params" คุณสมบัติมากกว่า "ข้อมูล" เมื่อคุณสร้างวัตถุ $ http ของคุณ:

$http({
   method: 'POST',
   url: serviceUrl + '/ClientUpdate',
   params: { LangUserId: userId, clientJSON: clients[i] },
})

ในตัวอย่างข้างต้นไคลเอนต์ [i] เป็นเพียงวัตถุ JSON (ไม่ต่อเนื่องในทางใดทางหนึ่ง) หากคุณใช้ "params" แทน "data" เชิงมุมจะทำให้วัตถุเป็นอันดับโดยใช้ $ httpParamSerializer: https://docs.angularjs.org/api/ng/serv// $ httpParamSerializer


2
ด้วยการใช้พารามิเตอร์แทนข้อมูล Angular จะวางข้อมูลในพารามิเตอร์ URL แทนที่จะเป็นเนื้อหาคำขอ นี่ไม่ใช่สิ่งที่คาดหวังจากการโพสต์แบบฟอร์ม
58

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.