追記。「ログインページを介さず Basic 認証」シリーズの投稿一覧です♪
- 【Nginx】Basic 認証をかける方法手順メモ | oki2a24
- cURL を使って Basic 認証が必要な PHP へ JSON データを POST する手順メモ | oki2a24
- AngularJS を使って PHP へ JSON データを POST する方法 | oki2a24
- AngularJS を使って Basic 認証が必要な PHP へ JSON データを POST できません>< | oki2a24
- AngularJS を使って Basic 認証が必要な PHP へ JSON データを POST するサンプルコード! | oki2a24
追記終わり!
AngularJS を使用してウェブブラウザのページでボタンを押すと、サーバへ JSON データを POST して PHP で受け取ってファイルに出力してみようと試みました!
苦労しましたので、記録を残しますわ♪
ポイント
- AngularJS で サーバに JSON をポストしたところエラーとなった。
- フロント側では、Access-Control-Allow-Origin のエラーが発生していた。
- サーバ側では method が POST ではなく、OPTIONS となっていた。
- クロスドメイン問題が原因だった。
- ちなみに、異なるドメインのデータにアクセスすることを、クロスドメインという。
- フロント側、サーバ側の両方で対応する必要がある。
- フロント側では、config で $httpProvider の Content-Type で x-www-form-urlencoded を設定する。
- サーバ側では、header(‘Access-Control-Allow-Origin: *’); を設定してやる。
エラーが発生した AngularJS のコード抜粋
var httpApp = angular.module('httpApp',[]);
httpApp.controller('SendController', ['$scope', '$http', function($scope, $http) {
$scope.dog = {
name: "Fido",
dob: new Date(),
legs: [1, 2, 3, 4]
};
var url = "https://oki2a24.com/basictest/json.php",
config = {
timeout: 5000
};
$scope.send = function() {
$http.post(url, $scope.dog, config).
success(function(data, status) {
$scope.data = data;
$scope.status = status;
}).
error(function(data, status) {
$scope.data = data || "Request failed";
$scope.status = status;
});
}
}]);
これでよいはずと思っておりましたけれども、この内容だけではエラーとなることがわかってきました。エラー内容と、解決方法を最終的なコードも含めて具体的に書いていきますの♪
エラー内容
フロント(AngularJS、HTML)側
XMLHttpRequest cannot load https://oki2a24.com/basictest/json.php. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
サーバ(Nginx、PHP)側
Nginx の access.log です。コマンド「tail -f /var/log/nginx/access.log | grep basictest」で拾うことができました。
999.158.2.78 - - [27/Jul/2015:22:59:10 +0900] "OPTIONS /basictest/json.php HTTP/1.1" 200 48 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36" "-" unix: - - [27/Jul/2015:22:59:10 +0900] "OPTIONS /basictest/json.php HTTP/1.0" 200 37 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36" "999.158.2.78"
method が POST ではなく、OPTIONS となっております。
修正1
を参考に、フロントの AngularJS 部分について、次のように config を追加いたしました。
httpApp.config(function($httpProvider) {
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;application/json;charset=utf-8';
});
サーバ側は修正しておりません。
修正1の結果
フロント(AngularJS、HTML)側では変わらず同じエラーがでておりました><。また、レスポンスも、次のように返却されませんでした。
Request failed 0
一方サーバ(Nginx、PHP)側では、POST として認識されるようになりました♪
999.158.2.78 - - [27/Jul/2015:23:13:50 +0900] "POST /basictest/json.php HTTP/1.1" 200 48 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36" "-" unix: - - [27/Jul/2015:23:13:50 +0900] "POST /basictest/json.php HTTP/1.0" 200 37 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36" "999.158.2.78"
PHP が JSON を受け取ることもできておりました!
# cat recieved_json.txt
object(stdClass)#1 (3) {
["name"]=>
string(4) "Fido"
["dob"]=>
string(24) "2015-07-27T14:13:46.588Z"
["legs"]=>
array(4) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
[3]=>
int(4)
}
}
#
もう少しですわね♪ガンバロ!
修正2
フロント側は修正せず、サーバ側の、PHP を修正いたしました。
コードの最初に次を追加しました。
header('Access-Control-Allow-Origin: *');
修正2の結果
フロント(AngularJS、HTML)側のエラーも出なくなりました!しかも、サーバからレスポンスも次のように正しく返って来ましたの♪
{"response":"OK"}
200
これで完璧ですわね♪
修正3。修正1は不要だった!?
と思い、
- 修正1を行う前の状態
- 修正2は行った状態
でどうなるか試してみました。
結果、すべての修正を始める前と同じ状態となってしまいました><。
つまりフロント側でエラーとなりレスポンスも帰ってこない、サーバ側でもウェブサーバのログを見ると method が POST ではなく OPTIONS で JSON の内容は NULL でしたの><。
以上のことから、修正1および修正2の両方が必要と結論づけられました。
最終的に成功したコード
フロント側の HTML ファイル
<!doctype html>
<html ng-app="httpApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
<script>
var httpApp = angular.module('httpApp',[]);
httpApp.config(function($httpProvider) {
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;application/json;charset=utf-8';
});
httpApp.controller('SendController', ['$scope', '$http', function($scope, $http) {
$scope.dog = {
name: "Fido",
dob: new Date(),
legs: [1, 2, 3, 4]
};
var url = "https://oki2a24.com/basictest/json.php",
config = {
timeout: 5000
};
$scope.send = function() {
$http.post(url, $scope.dog, config).
success(function(data, status) {
$scope.data = data;
$scope.status = status;
}).
error(function(data, status) {
$scope.data = data || "Request failed";
$scope.status = status;
});
}
}]);
</script>
</head>
<body>
<div ng-controller="SendController">
<h2>送信データ</h2>
{{dog}}
<ul>
<li>{{dog.name}}</li>
<li>{{dog.dob}}</li>
<li>{{dog.legs}}</li>
</ul>
<h2>送信</h2>
<button ng-click="send()">送信</button>
<h2>結果</h2>
<ul>
<li>{{data}}</li>
<li>{{status}}</li>
</ul>
</div>
</body>
</html>
サーバ側の PHP ファイル
<?php
header('Access-Control-Allow-Origin: *');
$json_string = file_get_contents('php://input');
ob_start();
var_dump(json_decode($json_string));
$out = ob_get_contents();
ob_end_clean();
file_put_contents('recieved_json.txt', $out);
// レスポンス header 関数無くてもレスポンスできたが、Volley だからなのかどうかは不明
header("HTTP/1.1 200 OK");
header("Status: 200");
header("Content-Type: application/json; charset=utf-8");
header('X-Content-Type-Options: nosniff');
$response = array('response' => 'OK');
echo json_encode($response);
おわりに
以前 cURL コマンドを使用してサーバへ JSON データを POST し、PHP で受け取ってファイルに出力する方法をまとめました。
今回は、cURL ではなく、AngularJS から POST してみたところ、ずいぶんと苦労してしまいました。
これから AngularJS を使って Basic 認証を通して JSON データを POST してみたいですの。
うまくいくかしら?楽しみですわ♪
以上です。

