以下のコードでは、AngularJSの$http
メソッドがURLを呼び出し、xsrfオブジェクトを「リクエストペイロード」として送信します(Chromeデバッガの「ネットワーク」タブで説明しています)。 jQueryの$.ajax
メソッドも同じ呼び出しを行いますが、xsrfを "Form Data"として送信します。
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() {}
});
渡される$ 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
AngularJS V1.4で追加された新しいサービスを使用するには、
ソリューションで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 () {});
この問題をめぐる混乱が続いたことで、私はそれについてブログ記事を書くように促しました。この記事で提案するソリューションは、現在の最高評価のソリューションよりも優れています。これは、$ httpサービス呼び出し用にデータオブジェクトをパラメータ化することに制限されていないためです。つまり、私の解決策を使えば、実際のデータオブジェクトを$ http.post()などに渡すことができ、それでも望ましい結果を得ることができます。
また、トップクラスの答えは$ .param()関数のページに完全なjQueryを含めることに依存していますが、私の解決策はjQueryにとらわれず、純粋なAngularJSに対応しています。
http://victorblog.com/2012/12/20/make-angularjs-http- service-behave-like-jquery-ajax/ /
お役に立てれば。
私は他のいくつかの答えを取り、何かを少しきれいにしました。あなたのapp.jsのあなたのangular.moduleの最後にこの.config()
呼び出しを置いてください:
.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("&");
});
}]);
AngularJS v1.4.0以降、 docsページ にリストされている規則に従って、任意のオブジェクトをHTTP要求の一部に変換する組み込みの$httpParamSerializer
サービスがあります。
それはこのように使用することができます:
$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";
現在の投稿に対してのみこれを行うには、request-objectのheaders
プロパティを変更する必要があります。
var req = {
method: 'POST',
url: 'http://example.com',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: $httpParamSerializer(formDataObj)
};
$http(req);
あなたはグローバルに振る舞いを定義することができます:
$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
});
回避策として、単にPOSTを受け取るコードをapplication/jsonデータに応答させることができます。 PHPのために、私は以下のコードを追加しました、それに私はフォームエンコードかJSONのどちらかでそれにPOSTをさせることができます。
//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
これらの答えは非常識なやり過ぎのように見えますが、時々、単純なほうが賢明です。
$http.post(loginUrl, "userName=" + encodeURIComponent(email) +
"&password=" + encodeURIComponent(password) +
"&grant_type=password"
).success(function (data) {
//...
あなたは以下の解決策で試すことができます
$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 */
});
Post用のアダプタサービスを作成します。
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)
})
}
})
これと他の関連したものについて詳しく説明している本当に素晴らしいチュートリアルがあります - AJAXフォームを提出する:The AngularJS Way 。
基本的には、フォームデータをURLエンコードされた文字列として送信することを示すようにPOSTリクエストのヘッダーを設定し、送信するデータを同じ形式に設定する必要があります。
$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)
});
JQueryのparam()ヘルパー関数は、データを文字列にシリアル化するためにここで使用されていますが、jQueryを使用しない場合は手動でも実行できます。
var fd = new FormData();
fd.append('file', file);
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(){
})
.error(function(){
});
チェックアウトしてください。 https://uncorkedstudios.com/blog/multipartformdata-file-upload-with-angularjs
Symfony2ユーザーの場合:
これを機能させるためにJavaScriptの中で何かを変更したくないのなら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);
私は現在AngularJSグーグルグループで次の解決策I found を使っています。
$ http post( '/ echo/json /'、 'json =' + encodeURIComponent(angular.toJson(data))、{ ヘッダー:{[.____ 'Content-Type': 'application/x-www-form-urlencoded; charset = UTF-8' } })。success(関数(データ){ $ scope.data = data; });
PHPを使用している場合、$ _POSTは自動的に読み込まれないため、これを読み取るにはSymfony 2 HTTPコンポーネントのRequest::createFromGlobals()
のようなものを使用する必要があります。
Content-Typeを設定するだけでは不十分です。送信前にフォームデータをURLエンコードしてください。 $http.post(url, jQuery.param(data))
完全な答え(角度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) {
});
AngularJSは、http-requestヘッダー内で次のコンテンツタイプを実行するのと同じように実行します。
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を使用できることです。
アプリの設定で -
$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'
}
これは直接的な答えではありませんが、デザインの方向性が少し異なります。
フォームとしてではなく、サーバーサイドオブジェクトに直接マッピングされるJSONオブジェクトとしてデータをポストするか、RESTスタイルのパス変数を使用します
XSRFキーを渡しているので、どちらのオプションもあなたのケースには適していないことがわかりました。これをパス変数にマッピングするのはひどい設計です。
http://www.someexample.com/xsrf/{xsrfKey}
本来/login
、/book-appointment
など、他のパスにもxsrfキーを渡したいと思うかもしれませんし、かわいいURLをめちゃくちゃにしたくないからです。
おもしろいことにオブジェクトフィールドとして追加することも適切ではありません。なぜなら今度はjsonオブジェクトのそれぞれでサーバーに渡すのでフィールドを追加しなければならないからです。
{
appointmentId : 23,
name : 'Joe Citizen',
xsrf : '...'
}
ドメインオブジェクトと直接の意味的な関連がない別のフィールドをサーバーサイドクラスに追加したくないことは確かです。
私の意見では、あなたのxsrfキーを渡すための最善の方法はHTTPヘッダ経由です。多くのxsrf保護サーバーサイドWebフレームワークライブラリはこれをサポートしています。 例えばJava Springでは、X-CSRF-TOKEN
ヘッダーを使用して渡すことができます 。
JSオブジェクトをUIオブジェクトにバインドするAngularの優れた機能により、フォームをまとめて投稿するというプラクティスを排除し、代わりにJSONを投稿することができます。 JSONはサーバーサイドのオブジェクトに簡単にデシリアライズでき、マップ、配列、ネストしたオブジェクトなどの複雑なデータ構造をサポートできます。
配列ペイロードに配列をどのように配置しますか?たぶんこれのように:
shopLocation=downtown&daysOpen=Monday&daysOpen=Tuesday&daysOpen=Wednesday
またはこれ:
shopLocation=downtwon&daysOpen=Monday,Tuesday,Wednesday
どちらもデザインが良くありません。
これが私が必要としていることです。フォームデータとしてログインデータを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
}