Travelport / travelport-uapi-tutorial-php

The travelport-uapi-tutorial-php is a PHP project for Universal API that will help you connect and code a standard workflow including Air, Vehicle, and Hotel.
35 stars 47 forks source link

Request for Universal Record Service from Javascript / Client Side #33

Open shubhamrathi97 opened 7 years ago

shubhamrathi97 commented 7 years ago

I was trying to use Universal Api service from front end. While making request, i am getting response code 500 'Request did not match allowed-feature list'. After searching on stack overflow, i come know that server need to configure for requests coming from client side because modern browser make a preflight request if request have custom header. Kindly provide a working example for javascript if it is available. Looking at php example, I set Authorization and Content-type header in my request. Here is a my code :

<html>

<head>
    <title>SOAP JavaScript Client Test</title>
    <script type="text/javascript">
        function soap() {
            var xmlhttp = new XMLHttpRequest();
            xmlhttp.open('POST', 'https://americas.universal-api.pp.travelport.com/B2BGateway/connect/uAPI/UniversalRecordService', true);

            // build SOAP request
            var sr =
                '<?xml version="1.0" encoding="utf-8"?>' +
                '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:com="http://www.travelport.com/schema/common_v30_0" xmlns:univ="http://www.travelport.com/schema/universal_v30_0">'+
                    '<soapenv:Header/>'+
                    '<soapenv:Body>'+
                        '<univ:UniversalRecordImportReq AuthorizedBy="user" ProviderCode="1G" ProviderLocatorCode="XNXZGU" TargetBranch="P7015266" TraceId="trace">'+
                            '<com:BillingPointOfSaleInfo OriginApplication="UAPI"/>'+
                        '</univ:UniversalRecordImportReq>'+
                    '</soapenv:Body>'+
                '</soapenv:Envelope>';

            xmlhttp.onreadystatechange = function() {
                    if (xmlhttp.readyState == 4) {
                        if (xmlhttp.status == 200) {

                            alert('done use firebug to see response');
                        }
                    }
                }
                // Send the POST request
            xmlhttp.withCredentials = true;    
            xmlhttp.setRequestHeader('Authorization','Basic VW5pdmVyc2FsIEFQSS91QVBJODY0NjA0NTY1Ni1iYTc1YTM5NTpDcGJ3NWRwZkVmTUdFQWpleEtlNWZtbnFD');
            xmlhttp.send(sr);
            // send request
            // ...
        }
    </script>
</head>

<body>
    <form name="Demo" action="" method="post">
        <div>
            <input type="button" value="Soap" onclick="soap();" />
        </div>
    </form>
</body>
<html>
vivekjyotipramanik commented 7 years ago

Hi shubham1997,

Thank you for your interest in Travelport Universal API. We don't have any JavaScript example currently available. We will check if you can provide one. Thanks.

Thanks & Regards Vivekjyoti Pramanik

shubhamrathi97 commented 7 years ago

Hi Vivekjyoti,

I will try to provide working JS example for travelport Universal API. Code in my last comment is working for other soap api's, you can use it as a example.

The issue is with travelport server. I think Universal Api server is not configure to handle preflight request. Preflight request are made by browser to check requested url is available or not.

I am getting following error in chrome console window on post request.

"XMLHttpRequest cannot load https://americas.universal-api.pp.travelport.com/B2BGateway/connect/uAPI/UniversalRecordService. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8887' is therefore not allowed access. The response had HTTP status code 500."

You need to configure Travelport Universal Api server to handle preflight request. I found following code on a blog to handle preflight request in php

// respond to preflights if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { // return only the headers and not the content // only allow CORS if we're doing a GET - i.e. no saving for now. if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']) && $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] == 'GET') { header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Headers: X-Requested-With'); } exit; } Original Post on https://remysharp.com/2011/04/21/getting-cors-working

I know its hard for a company to change backend code. But if you configure backend to handle preflight request then it will be easier for developers to use api in front-end also.

Kindly forward request to developers.

vivekjyotipramanik commented 7 years ago

Hi @shubham1997,

It is not an issue with uAPI. I tried the code you sent in IE 11 and I received the expected response. I have debugged the code with IE dev tools and I can see the response XMl there correctly. Could you please try using IE. Please let me know how it goes. Thanks.

Thanks & Regards Vivekjyoti Pramanik

shubhamrathi97 commented 7 years ago

@vivekjyotipramanik

It didn't for me in IE 11 also. I have attached screenshot on https://s22.postimg.org/70qnkdcnl/Screenshot_263.png . Is your IE 11 making options request? Have you tried on some other system?

vivekjyotipramanik commented 7 years ago

Hi shubham1997,

We have used the exact same code without any changes and it worked fine for us in IE11 without any kind of issues. We received the Status Code 200 and the correct response. Thanks.

Thanks & Regards Vivekjyoti Pramanik

shubhamrathi97 commented 7 years ago

@vivekjyotipramanik

Can you do Skype discussion. ?It will be much better to discuss on call while going through code Thanks

vivekjyotipramanik commented 7 years ago

Hi shubham1997,

I can schedule an webex if you can provide me your email id and your timezone along with preferred time. Thanks.

Thanks & Regards Vivekjyoti Pramanik

shubhamrathi97 commented 7 years ago

Thanks @vivekjyotipramanik

My email id is shubham.rathi97@gmail.com and I am available if you can schedule now (23:50 IST). I will be available till 01:00 IST.

vivekjyotipramanik commented 7 years ago

Hi shubham1997,

Unfortunately I am not available now. I will schedule something for tomorrow if that works for you. Thanks.

Thanks & Regards Vivekjyoti Pramanik

shubhamrathi97 commented 7 years ago

Are you available around 10:00 am IST tomorrow?

vivekjyotipramanik commented 7 years ago

Hi shubham1997,

Yes, I will be available at that time. I will schedule the webex and send the webex details to your email. Thanks.

Thanks & Regards Vivekjyoti Pramanik

shubhamrathi97 commented 7 years ago

Thanks @vivekjyotipramanik, I will be online on webex. Talk to you tomorrow.

--Shubham Rathi

jfunulab commented 7 years ago

Hi shubham1997,

Did you find a solution to your problem. I am currently having the same problem with sending request from my angular2 client app. If you did?kindly share.

@vivekjyotipramanik, could you point out what I am doing wrong here. The response i get is

"XMLHttpRequest cannot load https://emea.universal-api.pp.travelport.com/B2BGateway/connect/uAPI/AirService. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 500". Using google chrome for development.

Below is my code sample:

import { Injectable } from '@angular/core'; import { Http, Response, Headers } from '@angular/http'; import { Observable } from 'rxjs';

@Injectable() export class TravelportService{ baseurl = 'https://emea.universal-api.pp.travelport.com/B2BGateway/connect/uAPI/AirService';

constructor(private http: Http){}

getAirAvailablity(): Observable<any>{
    let headers = new Headers();
    headers.append("Content-Type", "text/xml")
    headers.append("Authorization", "Basic "+ btoa(username+":"+password));
    let requestBody = this.formatRequestBody();
   return this.http.post(this.baseurl, requestBody, {headers: headers}).map(this.extractData);
}

extractData(res: Response){
     return res.json();
}

formatRequestBody(){
   let body = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">'+
            '<soapenv:Header/>'+
            '<soapenv:Body>'+
                '<air:AvailabilitySearchReq xmlns:air="http://www.travelport.com/schema/air_v34_0" AuthorizedBy="uAPI6828794020-e9d96a12" TargetBranch="P7005024" TraceId="trace">'+
                    '<com:BillingPointOfSaleInfo xmlns:com="http://www.travelport.com/schema/common_v34_0" OriginApplication="UAPI"/>'+
                '<air:SearchAirLeg>'+
                    '<air:SearchOrigin>'+
                        '<com:Airport xmlns:com="http://www.travelport.com/schema/common_v34_0" Code="SYD"/>'+
                    '</air:SearchOrigin>'+
                    '<air:SearchDestination>'+
                        '<com:Airport xmlns:com="http://www.travelport.com/schema/common_v34_0" Code="MEL"/>'+
                    '</air:SearchDestination>'+
                    '<air:SearchDepTime PreferredTime="2017-09-24"/>'+
                '</air:SearchAirLeg>'+
                '<air:AirSearchModifiers>'+
                    '<air:PreferredProviders>'+
                        '<com:Provider xmlns:com="http://www.travelport.com/schema/common_v34_0" Code="1G"/>'+
                    '</air:PreferredProviders>'+
                '</air:AirSearchModifiers>'+
                '</air:AvailabilitySearchReq>'+
            '</soapenv:Body>'+
        '</soapenv:Envelope>';

    return body;
}
vivekjyotipramanik commented 7 years ago

Hi JFunu,

The issue you are getting is from the browser and UAPI is not getting the request from your side I believe.

Could you please try in IE and mozilla if you are getting the same issue there. Also, Could you please try in postman if you are getting the same error.

Thanks.

shubhamrathi97 commented 7 years ago

@JFunu Issue is related to CORS Header. I didn't get the solution for my problem because modern browser make a preflight request to API before actual request and UAPI are not configured to handle preflight request. My suggest would be use UAPI from your server side and get response.