YesMail v2 API: 400 Error with cURL request with PHP - php

I am trying to GET targeting from an MMID but am returning the following error. I know my credentials are correct and have combed over the documentation several times. "appTesting" in the response below is the name of my App in YesMail
INFO: HTTP Response Code was: 400 INFO: Response Follows... HTTP/1.1 400 Bad Request Access-Control-Allow-Origin: * Api-User: appTesting Content-Type: application/json Date: Wed, 29 Jul 2015 21:38:54 GMT Tracking-Id: f257bd75-47bb-40e7-a12c-5a45a042cbac X-Content-Type-Options: nosniff transfer-encoding: chunked Connection: keep-alive {"status":400,"message":"Could not open Hibernate Session for transaction; nested exception is java.lang.IllegalStateException: Cannot determine target DataSource for lookup key [appTesting]"}
I kind of stumped. What am I doing wrong?
<?php
$mmid = 'mmid';
$api_user = "appTesting";
$api_key = "api key";
$ym_api_url = 'https://api.yesmail.com/v2/masters/';
$curl_hdl = curl_init();
$curl_options = array(
CURLOPT_VERBOSE => 1,
CURLOPT_HEADER => TRUE,
CURLOPT_HTTPHEADER => array("Api-User: $api_user", "Api-Key: $api_key", "Accept: application/json",),
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => $ym_api_url.$mmid.'/target',
);
curl_setopt_array($curl_hdl, $curl_options);
$response = curl_exec($curl_hdl);
$http_response_code = curl_getinfo($curl_hdl, CURLINFO_HTTP_CODE);
curl_close($curl_hdl);
echo PHP_EOL . "INFO: HTTP Response Code was: " . $http_response_code . PHP_EOL;
if ( $response === false )
{
echo PHP_EOL . "ERROR: curl_exec() has failed." . PHP_EOL;
}
else
{
echo PHP_EOL . "INFO: Response Follows..." . PHP_EOL;
echo PHP_EOL . $response;
}
echo "<br/><br/>API USER: ".$api_user."<br/><br/>API KEY: ".$api_key;
?>

Related

HTTP Status 404 – Bad Request fsockopen php websocket client [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 3 days ago.
Improve this question
I am unable to connect with web socket though PHP client:
I am facing this issue:
HTTP/1.1 404 Vary: Origin Vary: Access-Control-Request-Method Vary: Access-Control-Request-Headers Content-Disposition: inline;filename=f.txt Content-Type: application/json Transfer-Encoding: chunked Date: Fri, 17 Feb 2023 11:54:45 GMT 67 {"timestamp":"2023-02-17T11:54:45.060+00:00","status":404,"error":"Not Found","path":"/app/notify.msg"} 0 HTTP/1.1 400 Content-Type: text/html;charset=utf-8 Content-Language: en Content-Length: 435 Date: Fri, 17 Feb 2023 11:54:45 GMT Connection: close
here is my complete code, wan to use stream type ws
` $host = '145.34.6.25';
$port = 8783;
$path = "/app/notify.msg"; // Request path
$timeout = 30;
// Timeout in seconds
// $WebSocketClient->connect($host,$port,'/ws');
$message = json_encode([
"company_id" => 23,
"payload" => [
"audience" => "user/company",
"message" => "Hello",
"userIs" => [1,2,3]
]
]);
$key = "753d345ec6b-b60343450-34540c0-a9f9-3bc324545cdc9906f";
$fp = fsockopen($host, $port, $errno, $errstr, $timeout);
dump($fp);
// Prepare the request header
$request = "GET " . $path . " HTTP/1.1\r\n";
$request .= "Host: " . $host . "\r\n";
$request .= "Upgrade: websocket\r\n";
$request .= "Connection: Upgrade\r\n";
$request .= "Sec-WebSocket-Key: " . $key . "\r\n";
$request .= "Sec-WebSocket-Version: 13\r\n\r\n";
$request.= "Authorization: token " . $key . "\r\n\r\n";
//$request.= $message;
// Send the request
fwrite($fp, $request);
// Get the response
$response = "";
while (!feof($fp)) {
$response .= fgets($fp, 1024);
}
// Close the connection
// fclose($fp);
// Output the response
echo $response;`
Here is stream type:
^ stream resource #588 ▼
timed_out: false
blocked: true
eof: false
stream_type: "tcp_socket/ssl"
mode: "r+"
unread_bytes: 0
seekable: false
options: []
}

php curl does not seem to send the intended POST variables

I am trying to retrieve a post from a simple POST to api.openweathermap.org.
The URL post should like like: api.openweathermap.org/data/2.5/weather?id=4215110&units=metric&appid=my_api_key
The php code I'm using is:
#!/usr/bin/php
<?php
define('WEATHER_CITY_CODE', 4215110) ; // Peachtree City, GA
define('WEATHER_UNITS', 'imperial') ; // or 'metric' or 'standard'
define('WEATHER_API_KEY', 'my_api_key') ; // Not the real key
$request = "api.openweathermap.org/data/2.5/weather" ;
$requestVariables = Array('id' => WEATHER_CITY_CODE
, 'units' => WEATHER_UNITS
, 'appid' => WEATHER_API_KEY
) ;
printf("Request query parameters should be: %s?%s\n", $request, http_build_query($requestVariables)) ;
$streamVerboseHandle = fopen('php://temp', 'w+') ;
$ch = curl_init($request) ;
curl_setopt($ch, CURLOPT_STDERR, $streamVerboseHandle) ;
curl_setopt($ch, CURLOPT_VERBOSE, true) ;
curl_setopt($ch, CURLOPT_POST, 1) ;
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query( $requestVariables )) ;
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true) ;
$weather_response = curl_exec($ch) ;
//if ($weather_response === FALSE)
{
printf("cUrl error (#%d): %s<br>\n",
curl_errno($ch),
htmlspecialchars(curl_error($ch)))
;
rewind($streamVerboseHandle);
$verboseLog = stream_get_contents($streamVerboseHandle);
echo "cUrl verbose information:\n",
htmlspecialchars($verboseLog), "\n";
}
curl_close($ch) ;
try {
$response_arr = json_decode($weather_response, true, 3, JSON_THROW_ON_ERROR) ;
print_r($response_arr) ;
}
catch (Exception $e) {
$response_file = "weather-response.json" ;
file_put_contents($response_file, $weather_response) ;
$lov->writeLogLine("Exception from send-sms.php: " . $e->getMessage()) ;
$lov->writeLogLine("Response text is: '" . $weather_response . "'"
, false, null, false, false) ;
$lov->writeLogLine("Response saved in " . $response_file) ;
throw new Exception("Failure in send-sms.php") ;
}
?>
When I run this code (even if the WEATHER_API_KEY value is set correctly, I get the following response:
Array
(
[cod] => 401
[message] => Invalid API key. Please see http://openweathermap.org/faq#error401 for more info.
)
Even if the correct API key is used. (Note: I can copy the value in the "Request query paraemters..." line and paste them into a browser to get the correct results without error.
So I added the curl debug code you see above, and it seems to indicate that curl is not sending my parameters. (see the POST /data/2.5/weather HTTP/1.1 below.) I'm not sure why. While I'm not accustomed to using (nor needing) that curl debug information, it seems to me that I should see /data/2.5/weather?id=4... in its place.
I saw this article, but I don't think it applies here...
Can you help?
Process output is:
> ./getweathermap.php
Request query parameters should be: api.openweathermap.org/data/2.5/weather?id=4215110&units=imperial&appid=my_api_key
cUrl error (#0): <br>
cUrl verbose information:
* Trying 192.241.245.161:80...
* TCP_NODELAY set
* Connected to api.openweathermap.org (192.241.245.161) port 80 (#0)
> POST /data/2.5/weather HTTP/1.1
Host: api.openweathermap.org
Accept: */*
Content-Length: 42
Content-Type: application/x-www-form-urlencoded
* upload completely sent off: 42 out of 42 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 401 Unauthorized
< Server: openresty
< Date: Sun, 27 Feb 2022 01:45:01 GMT
< Content-Type: application/json; charset=utf-8
< Content-Length: 107
< Connection: keep-alive
< X-Cache-Key: /data/2.5/weather?
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Methods: GET, POST
<
* Connection #0 to host api.openweathermap.org left intact
Array
(
[cod] => 401
[message] => Invalid API key. Please see http://openweathermap.org/faq#error401 for more info.
)

PHP curl - obtain response headers when error exists?

I am calling a REST service using php curl. If an error occurs (for example because I posted invalid data) the REST server returns error code 400 and provides informative application error details in the response header custom field.
However, when error 400 occurs the header is not provided in the result from curl_exec() at it returns FALSE even though setopt as been provided. Headers are seen if code returned is 2xx.
curl_setopt($curl,CURLOPT_HEADER, 1);
Is there any way to get the response headers on errors >= 400?
In the example below, I'm using https://httpstat.us/400 to simulate a HTTP 400 response code.
<?php
// create curl resource
$ch = curl_init();
// set url that responds with HTTP 400 status
curl_setopt($ch, CURLOPT_URL, "https://httpstat.us/400");
//return the transfer as a string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//enable headers
curl_setopt($ch, CURLOPT_HEADER, 1);
//get only headers
curl_setopt($ch, CURLOPT_NOBODY, 1);
// $output contains the output string
$output = curl_exec($ch);
// close curl resource to free up system resources
curl_close($ch);
$headers = [];
$output = rtrim($output);
$data = explode("\n",$output);
$headers['status'] = $data[0];
array_shift($data);
foreach($data as $part){
//some headers will contain ":" character (Location for example), and the part after ":" will be lost, Thanks to #Emanuele
$middle = explode(":",$part,2);
//Supress warning message if $middle[1] does not exist, Thanks to #crayons
if ( !isset($middle[1]) ) { $middle[1] = null; }
$headers[trim($middle[0])] = trim($middle[1]);
}
// Print all headers as array
print_r($headers);
This returns
Array
(
[status] => HTTP/1.1 400 Bad Request
[Cache-Control] => private
[Content-Length] => 15
[Content-Type] => text/plain; charset=utf-8
[Server] => Microsoft-IIS/10.0
[X-AspNetMvc-Version] => 5.1
[Access-Control-Allow-Origin] => *
[X-AspNet-Version] => 4.0.30319
[X-Powered-By] => ASP.NET
[Set-Cookie] => ARRAffinity=93fdbab9d364704de8ef77182b4d13811344b7dd1ec45d3a9682bbd6fa154ead;Path=/;HttpOnly;Domain=httpstat.us
[Date] => Wed, 13 Nov 2019 23:31:51 GMT
)
That array with all response headers matches up with what I get when I use curl from my terminal:
curl -v https://httpstat.us/400
returns
< HTTP/1.1 400 Bad Request
< Cache-Control: private
< Content-Length: 15
< Content-Type: text/plain; charset=utf-8
< Server: Microsoft-IIS/10.0
< X-AspNetMvc-Version: 5.1
< Access-Control-Allow-Origin: *
< X-AspNet-Version: 4.0.30319
< X-Powered-By: ASP.NET
< Set-Cookie: ARRAffinity=93fdbab9d364704de8ef77182b4d13811344b7dd1ec45d3a9682bbd6fa154ead;Path=/;HttpOnly;Domain=httpstat.us
< Date: Wed, 13 Nov 2019 23:33:19 GMT
Here's another option using the CURLOPT_HEADERFUNCTION option with a callback function:
<?php
// this holds the response headers from the curl call
$responseHeaders = array();
// this function processes the response headers from the curl call
function curlResponseHeaderCallback($ch, $headerLine) {
global $responseHeaders;
// trim all the whitespace on this line
$trimmed = trim($headerLine);
// only proceed if the string is not empty
if(!empty($trimmed)) {
// headers follow Key: Value format
$split = explode(':', $trimmed);
// only proceed if the value of the header is not empty
if(!empty($split[1])) {
// $split[0] is the Key of the response header
// $split[1] is the Value of the response header, which can also have whitespace
$responseHeaders[$split[0]] = trim($split[1]);
}
}
// who knows why, but you have to return this.
return strlen($headerLine);
}
// get cURL resource
$ch = curl_init();
// set url
curl_setopt($ch, CURLOPT_URL, "https://httpstat.us/400");
curl_setopt($ch, CURLOPT_HEADERFUNCTION, "curlResponseHeaderCallback");
// send the request
curl_exec($ch);
// close the handle
curl_close($ch);
print_r($responseHeaders);
returns
Array
(
[Cache-Control] => private
[Content-Length] => 15
[Content-Type] => text/plain; charset=utf-8
[Server] => Microsoft-IIS/10.0
[X-AspNetMvc-Version] => 5.1
[Access-Control-Allow-Origin] => *
[X-AspNet-Version] => 4.0.30319
[X-Powered-By] => ASP.NET
[Set-Cookie] => ARRAffinity=93fdbab9d364704de8ef77182b4d13811344b7dd1ec45d3a9682bbd6fa154ead;Path=/;HttpOnly;Domain=httpstat.us
[Date] => Wed, 13 Nov 2019 23
)

Http request with PHP Bad Request Error

I try to access an API for a web app which will return the data in json format. The idea is to configure the header for the request to be read properly. An example request provided would be:
GET /links/{linkKey}/response HTTP/1.1
Access: *MY SECRET KEY*
Account: *MY ACCOUNT KEY*
Accept: application/json
Accept-Encoding: gzip
Host: localhost
User-Agent: YourApp/1.0
This example request should return this example response:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Encoding: gzip
Transfer-Encoding: chunked
Vary: Accept-Encoding
{
"headers": [
"column_a",
"column_b",
"column_c"
],
"rows": [
[
"text 1",
143.22,
true
],
[
"text 2",
98,
false
],
[
"text 3",
24.9,
false
],
[
"value 4",
242,
false
],
[
"value 5",
32,
true
]
],
"totalRows": 5
}
Based on this, I wrote the following code:
<?php
// Set header
header('Content-type: application/json');
// See https://app.example.com/#/api
$endpoint = "https://api.example.com/"; // The URL for API access
$api_key = "*MY API_KEY*";
$account_id = "*MY ACCOUNT KEY*";
$access_key = md5($account_id . $api_key);
$link_key = '*MY LINK KEY*'; //Edit your runs inside the app to get their ID
$curl_h = curl_init($endpoint);
curl_setopt($curl_h, CURLOPT_HTTPHEADER,
array(
"GET /links/" . $link_key . "/latest/result HTTP/1.1\r\n",
"Access:" . $access_key . "\r\n",
"Account:" . $account_id . "\r\n",
"Accept: application/json\r\n",
"Accept-Encoding: gzip\r\n",
"Host: localhost\r\n",
"User-Agent: CS-PHP-CLIENT/1.0\r\n",
"Content-Type: application/json\r\n"
)
);
// Store to variable
curl_setopt($curl_h, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($curl_h);
curl_close($curl_h);
var_dump($response);
This outputs a 400 Bad Request error in the browser:
string(298) "<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
</p>
<hr>
<address>Apache/2.4.7 (Ubuntu) Server at example.com Port 80</address>
</body></html>
"
As you can see from above, the regulation of the provider is that the access_key must be encrypted using md5(). Given that at least string(298) appears, I alter the code to var_dump($curl_h), instead of var_dump($response). This eventually outputs an unknown response:
resource(2) of type (Unknown)
I rewrote the code into something different:
<?php
// See https://app.example.com/#/api
$endpoint = "https://api.example.com/"; // The URL for API access
$api_key = "*MY API_KEY*";
$account_id = "*MY ACCOUNT KEY*";
$access_key = md5($account_id . $api_key);
$link_key = '*MY LINK KEY*'; //Edit your runs inside the app to get their ID
// Create a stream
$opts = array(
'http'=>array(
'method'=>"GET",
'header'=>"GET /links/" . $link_key . "/latest/result HTTP/1.1\r\n" .
"Access:" . $access_key . "\r\n" .
"Account:" . $account_id . "\r\n" .
"Accept: application/json\r\n" .
"Accept-Encoding: gzip\r\n" .
"Host: localhost\r\n" .
"User-Agent: CS-PHP-CLIENT/1.0\r\n" .
"Content-Type: application/json\r\n"
)
);
$context = stream_context_create($opts);
// Open the file using the HTTP headers set above
$file = file_get_contents($endpoint, false, $context);
var_dump($file);
The following response appears in the browser when I run this code:
bool(false)
I don't know why this doesn't work.
NB: I'm using a localhost on my pc which loads other php files and their respective code correctly.
API Endpoint: https://api.example.com/
Text Encoding: All requests must be encoded in UTF-8 - and all responses are UTF-8 encoded.

php curl not getting same response as fiddler

This is my PHP code :
$source = $_POST['source'];
$destination = $_POST['destination'];
$class = $_POST['class'];
$day = $_POST['day'];
$month = $_POST['month'];
$data = array(
'lccp_src_stncode_dis' => $source,
'lccp_dstn_stncode' => $destination,
'lccp_classopt' => $class,
'lccp_day' => $day,
'lccp_month' => $month
);
# Create a connection
$url = 'data as per raw req ';
$ch = curl_init($url);
echo $ch." <br>";
# Form data string
$postString = http_build_query($data);
echo $postString;
$header = array (
'Host' => 'data as per raw req '
'Connection'=> 'keep-alive',
'Content-Length'=> '180',
'Cache-Control'=> 'max-age=0',
'Accept'=> 'text/html',
'Origin'=> 'data as per raw req ',
'User-Agent' => '',
'Content-Type' => 'application/x-www-form-urlencoded',
'Referer': 'data as per raw req '
'Accept-Encoding'=> '',
'Accept-Language' => 'en-US,en;q=0.8'
);
# Setting options
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postString);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
//# Get the response
curl_setopt($ch, CURLOPT_POSTFIELDS,
$response = curl_exec($ch);
curl_close($ch);
#print response
echo "
$response
";
receiving form data from:
<html>
<form method="post" action="poster.php">
<table>
<tr><td>source:</td><td><input type="text" name="source"></td></tr>
<tr><td>destination:</td><td><input type="text" name="destination"></td></tr>
<tr><td>day:</td><td><input type="text" name="day"></td></tr>
<tr><td>month:</td><td><input type="text" name="month"></td></tr>
<tr><td>class:</td><td><input type="text" name="class"></td></tr>
<tr><td><input type="submit" name="submit" value="Submit"></td>
<td><input type="reset" name="reset" value="Reset"></td></tr>
</table>
</form>
</html>
this is the raw request
POST http://www.indianrail.gov.in/cgi_bin/inet_srcdest_cgi_date.cgi HTTP/1.1
Host: www.indianrail.gov.in
Connection: keep-alive
Content-Length: 91
Cache-Control: max-age=0
Accept: text/html
Origin: **<---modified since I can't post more than 2 links
User-Agent:
Content-Type: application/x-www-form-urlencoded
Referer: ** <---modified since I can't post more than 2 links
Accept-Encoding:
Accept-Language: en-US,en;q=0.8
lccp_src_stncode_dis=ndls&lccp_dstn_stncode=HYB&lccp_classopt=SL&lccp_day=26&lccp_month=6
Fiddler is giving the appropriate response from the cgi, whereas the php script just shows the html container, I've been stuck for over an hour ! Please help !
EDIT: output from verbose :
* Adding handle: conn: 0x2cab910
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 3 (0x2cab910) send_pipe: 1, recv_pipe: 0
* About to connect() to www.indianrail.gov.in port 80 (#3)
* Trying 203.176.113.78...
* Connected to www.indianrail.gov.in (203.176.113.78) port 80 (#3)
> POST /cgi_bin/inet_srcdest_cgi_date.cgi HTTP/1.1
Host: www.indianrail.gov.in
Accept: */*
http://www.indianrail.gov.in
http://www.indianrail.gov.in/know_Station_Code.html
Content-Length: 89
Content-Type: application/x-www-form-urlencoded
* upload completely sent off: 89 out of 89 bytes
< HTTP/1.1 200 OK
< Date: Fri, 27 Jun 2014 05:38:17 GMT
* Server Apache/2.2.15 (Red Hat) is not blacklisted
< Server: Apache/2.2.15 (Red Hat)
< Connection: close
< Transfer-Encoding: chunked
< Content-Type: text/html; charset=UTF-8
<
* Closing connection 3
^Off topic: Why did it just let me post links this time, it should have been recognized as links ?
Also, I would compare sessions in fiddler, but fiddler shows the request to my own app on local host, not from my app to the indian railways site.
screenshot :
NEVERMIND, NOT ENOUGH REP
EDIT:
I'll be happy if someone can show me how to make this request with http_request2 as well I've posted the exact raw request that gives me the required output with fiddler in the comments, so no, I'm not missing any authentication and cookie headers and the like
header is not to be entered as an associative array, this is wrong :
$header = array (
'Host' => 'data as per raw req '
'Connection'=> 'keep-alive',
'Content-Length'=> '180',
'Cache-Control'=> 'max-age=0',
'Accept'=> 'text/html',
'Origin'=> 'data as per raw req ',
'User-Agent' => '',
'Content-Type' => 'application/x-www-form-urlencoded',
'Referer': 'data as per raw req '
'Accept-Encoding'=> '',
'Accept-Language' => 'en-US,en;q=0.8'
);
correct method :
$header = array (
'Host:*data as per raw req* '
'Connection:keep-alive',
'Content-Length:180',
'Cache-Control:max-age=0',
'Accept:text/html',
'Origin:*data as per raw req* ',
'User-Agent:',
'Content-Type:application/x-www-form-urlencoded',
'Referer:*data as per raw req* '
'Accept-Encoding:',
'Accept-Language:en-US,en;q=0.8'
);
even the data entered in the associative array I've used is formatted to a url encoded post string, apparently everything pretty much has to be entered as it is in a raw http request. cURL doesn't really do any formatting.

Categories