javascriptangularjscorscross-domainskyscanner

Angular Ionic POST 405 (Method Not Allowed), using Chrome


I managed to send a $http.post to skyscannerAPI: http://partners.api.skyscanner.net/apiservices/pricing/v1.0 However, I get the POST http://partners.api.skyscanner.net/apiservices/pricing/v1.0 405 (Method Not Allowed), I searched through Info someone said it is perhaps due to I'm using Chrome, So I installed the extension Allow-Control-Allow-Origin, but it is still showing the error. The complete error message showing that like this:

POST http://partners.api.skyscanner.net/apiservices/pricing/v1.0 405 (Method Not Allowed)
    (anonymous) @ ionic.bundle.js:25005
    sendReq @ ionic.bundle.js:24798
    serverRequest @ ionic.bundle.js:24508
    processQueue @ ionic.bundle.js:29132
    (anonymous) @ ionic.bundle.js:29148
    $eval @ ionic.bundle.js:30400
    $digest @ ionic.bundle.js:30216
    $apply @ ionic.bundle.js:30508
    (anonymous) @ ionic.bundle.js:65428
    defaultHandlerWrapper @ ionic.bundle.js:16792
    eventHandler @ ionic.bundle.js:16780
    triggerMouseEvent @ ionic.bundle.js:2953
    tapClick @ ionic.bundle.js:2942
    tapTouchEnd @ ionic.bundle.js:3069

The (anonymous) @ ionic.bundle.js:25005 is following code:

xhr.send(isUndefined(post) ? null : post);

My code is as following:

//service.js    
.service('skyscanner',function($http){
      var baseUrl= "http://partners.api.skyscanner.net/apiservices/pricing/v1.0";
      var bodyInfo= {
            body: {
              apikey: My_API_KEY,
              Country: "CA",
              Currency: "CAD",
              //more data......   
            }
          };
      this.getKey= function(){  
        var require_sessionkey= $http({
          method:"POST",
          url:baseUrl,
          data: bodyInfo,
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Accept' :'application/json'
          }
        })
        .success(function successCallback() {
          var polling={};
          var session_key = require_sessionkey.headers["location"];
          (function(){
            polling=$http.get(session_key, {query: {apikey: My_API_KEY}});  
          })();
          return polling;
        }).error(function errorCallback() {
          console.log("something gets wrong: "+ require_sessionkey);
        });
      };
    })

//controller.js   
.controller('FlightSearchCtrl',function($scope,skyscanner,FlightInfos){
          $scope.list = [];
          $scope.text = 'hello';
          $scope.skyscannerPost= function(){
            var polling=skyscanner.getKey();
            $scope.polling=polling;
          };
        })

Solution

  • After a couple of hours research, I found the answer. I need to serialize my data because the Content-Type: 'application/x-www-form-urlencoded', which means that the body of the HTTP message sent to the server is essentially one giant query string -- name/value pairs are separated by the ampersand (&), and names are separated from values by the equals symbol (=). An example of this would be(reference https://stackoverflow.com/questions/4007969/application-x-www-form-urlencoded-or-multipart-form-data):

    MyVariableOne=ValueOne&MyVariableTwo=ValueTwo
    

    if the data is not serialized, it looks like:

     console.log(bodyInfo);
    //=> Object {apikey: "ds436195492025844505223424234232173", country: "CA", currency: "CAD", locale: "zh_Hans_CN", adults: 1…}
    

    After it is serialized:

        console.log(bodyInfoSerialied);
      //=>apikey=ds436195492025844505223424234232173&country=CA&currency=CAD&locale=zh_Hans_CN&adults=1&children=0&infants=0&originPlace=YVR&destinationPlace=SHA&outboundDate=2017-01-19&inboundDate=2017-01-23&locationSchema=Iata&cabinClass=Economy
    

    Thanks to the answer I post the edited code below:

        .service('skyscanner',function($http){
          var baseUrl= "http://partners.api.skyscanner.net/apiservices/pricing/v1.0";
          var bodyInfo= {
                  'apikey': 'ds43619549203213123211202173',
                  "country": "CA",
                  "currency": "CAD",
                  "locale": "zh_Hans_CN",
                  //...       
              };
    //new added serialize().
          serialize = function(obj, prefix) {
            var str = [], p;
            for(p in obj) {
              if (obj.hasOwnProperty(p)) {
                var k = prefix ? prefix + "[" + p + "]" : p, v = obj[p];
                str.push((v !== null && typeof v === "object") ?
                  serialize(v, k) :
                  encodeURIComponent(k) + "=" + encodeURIComponent(v));
              }
            }
            return str.join("&");
          }
    //serialize the body.
          var bodyInfoSerialied = serialize(bodyInfo);
          console.log(bodyInfo);
          console.log(bodyInfoSerialied);
          this.getKey= function(){  
            var require_sessionkey= $http({
              method:"POST",
              url:baseUrl,
              headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
                'Accept' :'application/json'
              },
              data:bodyInfoSerialied
            })
            .success(function successCallback(require_sessionkey) {
              console.log(require_sessionkey);
              var polling={};
              var session_key = require_sessionkey.headers["Location"];
              (function(){
                polling=$http.get(session_key, {query: {apikey: 'ds43619549203213123211202173'}});  
              })();
              return polling;
            }).error(function errorCallback(require_sessionkey) {
              console.log("something gets wrong: "+ require_sessionkey);
              console.log("bodyInfoSerialied: "+ bodyInfoSerialied);
            });
          };
        })
    

    Notice the code still gets something wrong, but the 405 error is solved at least.