Twitter Api Search doesn't work through proxy - php

I have a weird problem with the new twitter api. I followed the very good answer from this question to create a search in twitter and used the TwitterAPIExchange.php from here.
Everything works fine as long as I am directly calling it from my server with CURL. But in the live environment I have to use a proxy with Basic Authentication.
All I've done is add the proxy authentication to the performRequest function:
if(defined('WP_PROXY_HOST') && defined('WP_PROXY_PORT') && defined('WP_PROXY_USERNAME') && defined('WP_PROXY_PASSWORD'))
{
$options[CURLOPT_HTTPPROXYTUNNEL] = 1;
$options[CURLOPT_PROXYAUTH] = CURLAUTH_BASIC;
$options[CURLOPT_PROXY] = WP_PROXY_HOST . ':' . WP_PROXY_PORT;
$options[CURLOPT_PROXYPORT] = WP_PROXY_PORT;
$options[CURLOPT_PROXYUSERPWD] = WP_PROXY_USERNAME . ':' . WP_PROXY_PASSWORD;
}
Without the proxy I get a JSON response. But with the proxy I get:
HTTP/1.1 200 Connection established
HTTP/1.1 400 Bad Request
content-type: application/json; charset=utf-8
date: Fri, 20 Dec 2013 09:22:59 UTC
server: tfe
strict-transport-security: max-age=631138519
content-length: 61
Proxy-Connection: Keep-Alive
Connection: Keep-Alive
Set-Cookie: guest_id=v1%3A138753137985809686; Domain=.twitter.com; Path=/; Expires=Sun, 20-Dec-2015 09:22:59 UTC
Age: 0 {"errors":[{"message":"Bad Authentication data","code":215}]}
I've tried to simulate a proxy in my local environment with Charles Proxy, and it worked.
I'm assuming the proxy is either not sending the Authentication Header, or is changing data somehow.
Anybody with a clue....
EDIT:
Using the HTTP API works but HTTPS fails. I've tried CURLOPT_SSL_VERIFYPEER and CURLOPT_SSL_VERIFYHOST set to FALSE but the twitter SSL is valid so this is not recommended

Is your proxy response caches or is the date in the proxy response old because you did perform the API call on the 20th december?
If it is cached maybe your proxy is having a cached reply from an actual invalid request?

Related

PHP header() not sending custom message

I would like my server to return a header with a custom message. Using the header() function, I can generate the appropriate headers but the message always reverts to some standard string, not the text I provide.
For example, if I put this in my server code
header ($_SERVER['SERVER_PROTOCOL'] . ' 501 test error', true, 501);
I always see 501 Not Implemented in my client. For clients, I've used Postman and also my Xamarin Forms client app. With the latter, I stopped it in the debugger to look at the text returned from httpClient.GetAsynch().
I've also tried having only the first parameter
header ($_SERVER['SERVER_PROTOCOL'] . ' 501 test error');
but I get the same results.
Here's another try. I returned this:
header ($_SERVER['SERVER_PROTOCOL'] . ' Status: 501 test error', true, 501);
But curl on a command line shows this:
HTTP/1.1 200 OK
Connection: Keep-Alive
X-Powered-By: PHP/5.6.40
Content-Type: text/html; charset=UTF-8
Content-Length: 0
Date: Thu, 24 Dec 2020 17:20:54 GMT
Server: LiteSpeed
Alt-Svc: quic=":443"; ma=2592000; v="43,46", h3-Q043=":443"; ma=2592000, h3-Q046=":443"; ma=2592000, h3-Q050=":443"; ma=2592000, h3-25=":443"; ma=2592000, h3-27=":443"; ma=2592000
And, if I take out "Status: ", I get this:
HTTP/1.1 501 Not Implemented
Connection: Keep-Alive
X-Powered-By: PHP/5.6.40
Content-Type: text/html; charset=UTF-8
Content-Length: 0
Date: Thu, 24 Dec 2020 17:28:09 GMT
Server: LiteSpeed
Alt-Svc: quic=":443"; ma=2592000; v="43,46", h3-Q043=":443"; ma=2592000, h3-Q046=":443"; ma=2592000, h3-Q050=":443"; ma=2592000, h3-25=":443"; ma=2592000, h3-27=":443"; ma=2592000
header("HTTP/1.1 …") is a workaround for CGI setups. It's not a HTTP header as such. It's transformed and cleansed by PHP-FPM in most cases: https://github.com/php/php-src/blob/97d2dd0f90b328e771b60634cc377fd20eececbc/sapi/fpm/fpm/fpm_main.c#L307 if sent that way.
This is how you set a Status: header:
header("Status: 429 Begone!");
Now, if your webserver (LiteSpeed) strips out custom messages, then that's that. Nothing PHP can do about it. You'll have to find a server config workaround then. (e.g. Header add with some if= for Apache)
In short, give it a rest with SERVER_PROTOCOL unless your SAPI binding requires it. Upgrading PHP is an option if you run into troubles otherwise. Else you'll have to live with the standardized status message.
After doing some reading, I believe the right way to provide a custom message for an error is to send it in the body, not the header.
So, for example, to provide a custom message "missing weight=x parameter, one can use this code:
http_response_coede (400);
print json_encode (array ('error' => 400,
'message' => 'missing weight=x parameter');
Then, in your client, you parse this json string from the result body.
This might also happen if you use HTTP/2, which no longer has the status text.

file_get_contents - getting real complete HTTP answer (not just headers)

I'm trying to get full HTTP answer over a call to file_get_contents function. I'm doing an HTTP POST call, putting credentials to login to my website, process some work, then return a HTTP answer to the caller.
When credentials are not good, i send a HTTP 403 return code, with a message as follow (Raw HTTP response as shown in SoapUI) :
HTTP/1.1 403 Forbidden
Server: Apache-Coyote/1.1
X-UA-Compatible: IE=edge
Pragma: no-cache
Cache-Control: no-cache
Expires: Mon, 05 Jun 2017 09:02:13 GMT
Content-Type: text/plain;charset=utf-8
Content-Length: 515
Date: Mon, 05 Jun 2017 09:02:13 GMT
L'authentification user/password n'est pas autorisée pour le login 'sebastien' depuis l'adresse '127.0.0.1'.
How can i get the message at bottom after calling file_get_contents in php ? Message is not in the headers, so $http_response_header won't work. Is there a way to do so ?
You could create an HTTP stream context to use with file_get_contents() then call stream_get_meta_data() but personally I would just use Curl with CURLOPT_HEADER=true
Note that since the service is returning a 403 rather than a 401, then you're going to need cookies (if it is possible at all) to authenticate. For that you will need Curl.
A HTTP response body should be separated from headers by an empty line: https://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html
Then the body should be available as a result of file_get_contents call.
the HTTP context option ignore_errors is needed to get the content body of the page when an HTTP error code (4XX or 5XX) is returned.

Link between PHP and HTTP Request and Response Messages

When I did a networks course I learned about HTTP Request and Response messages and I know how to code in php reasonably enough to get around. Now my question is, the PHP has to have some link to HTTP request and response message but how. I can't seem to see the link between the two. My reasoning for asking this is that I am using the Twitter API console tool to query their api. The tool sends the following HTTP request:
GET /1.1/search/tweets.json?q=%40twitterapi HTTP/1.1
Authorization:
OAuth oauth_consumer_key="DC0se*******YdC8r4Smg",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1410970037",oauth_nonce="2453***055",oauth_version="1.0",oauth_token="796782156-ZhpFtSyPN5K3G**********088Z50Bo7aMWxkvgW",oauth_signature="Jes9MMAk**********CxsKm%2BCJs%3D"
Host:
api.twitter.com
X-Target-URI:
https://api.twitter.com
Connection:
Keep-Alive
and then I get a HTTP response:
HTTP/1.1 200 OK
x-frame-options:
SAMEORIGIN
content-type:
application/json;charset=utf-8
x-rate-limit-remaining:
177
last-modified:
Wed, 17 Sep 2014 16:07:17 GMT
status:
200 OK
date:
Wed, 17 Sep 2014 16:07:17 GMT
x-transaction:
491****a8cb3f7bd
pragma:
no-cache
cache-control:
no-cache, no-store, must-revalidate, pre-check=0, post-check=0
x-xss-protection:
1; mode=block
x-content-type-options:
nosniff
x-rate-limit-limit:
180
expires:
Tue, 31 Mar 1981 05:00:00 GMT
set-cookie:
lang=en
set-cookie:
guest_id=v1%3A14109******2451388; Domain=.twitter.com; Path=/; Expires=Fri, 16-Sep-2016 16:07:17 UTC
content-length:
59281
x-rate-limit-reset:
1410970526
server:
tfe_b
strict-transport-security:
max-age=631138519
x-access-level:
read-write-directmessages
So how do these HTTP request and response messages fit into PHP? Does PHP auto generate this? How do I add authorization to PHP requests etc? I'm confused about the deeper workings of PHP
When the client sends the HTTP request to the server, there has to be something to receive the HTTP request, which is called a web server. Examples of web servers are Apache, IIS, Nginx, etc. You can also write your own server, which can handle input however it wants. In this case, I'll assume that you are requesting a PHP file.
When the web server captures the HTTP request, it determines how it should be handled. If the file requested is tweets.json, it will go make sure that file exists, and then pass control over to PHP.
PHP then begins its execution, and performs any logic that the script needs to do, meaning it could go to the database, it reads, writes and makes decisions based cookies, it does math, etc.
When the PHP script is done, it will return a HTML page as well as a bunch of headers back to the web server that called it. From there, the web server turns the HTML page and headers back into a HTTP request to respond.
That is a pretty simple overview, and web servers can work in many different ways, but this is a simple example of how it could work in a introductory use-case. In more complex scenarios, people can write their own web servers, which perform more complex logic inside of the web server software, rather than passing it off to PHP.
When it comes down to it, PHP files are just scripts that the web server executes when they are called, they provide the HTTP request as input, and get a web page and headers as output.

Pingdom monitoring tool detecting HTTP 302 Found responses intermittently

I am experiencing intermittent issues when using the Pingdom monitoring tool to check the status of my website.
Every 10-15 minutes I get an alert to say that a 302 has been found. What I can't understand is - i'm not doing any 302 temporary redirects. I am, however, doing 301 redirects (in certain circumstances).
Could this be a false positive from Pingdom?
Also, I have a redirect in code that does this. Would not specifying the HTTP response code
cause an issue here?
header('Location: http://www.ayrshireminis.com');
exit();
The Pingdom data:
Request 1
GET / HTTP/1.0
User-Agent: Pingdom.com_bot_version_1.4_(http://www.pingdom.com/)
Host: www.ayrshireminis.com
Received header
302 Found
Date: Tue, 24 Jul 2012 13:13:25 GMT
Server: Apache
Set-Cookie: prev_session_id=2a7001f5caa79bd36995953bf4853675; expires=Thu, 23-Aug-2012 13:13:25 GMT; path=/; domain=ayrshireminis.com
Location: http://www.ayrshireminis.com/
Vary: Accept-Encoding
Connection: close
Content-Type: text/html; charset=ISO-8859-1
Looks to me like a cookie is being set on the response, then redirecting you to the same page. Because Pingdom uses a number of different monitoring sources, that cookie redirect behavior will cause a lot of problems. Then again, you may need it for actual website visitors.
Rather than monitor the root of the webpage, I would recommend creating a separate /status page just for Pingdom that:
Doesn't set or use cookies
Performs a cheap end-to-end health check of the application and backing services
Returns a 200 response code only if everything checks out OK

PHP cURL: HTTP headers show 302 and cookies set, cookies are saved and sent, same headers appear?

This is kind of a carry on from a question asked yesterday: Can't seem to get a web page's contents via cURL - user agent and HTTP headers both set?
I'm attempting to access a url's contents, the problem is the way this url handles request.
The url: http://www.deindeal.ch/deals/atlas-grand-hotel-2-naechte-30-2/
First request (without cookies):
After "learning" to use curl in the command line (props to #d3v3us), a simple request curl -i http://www.deindeal.ch/deals/atlas-grand-hotel-2-naechte-30-2/ shows the following:
curl -i http://www.deindeal.ch/deals/atlas-grand-hote
l-2-naechte-30-2/
HTTP/1.1 302 FOUND
Date: Fri, 30 Dec 2011 13:15:00 GMT
Server: Apache/2.2.16 (Debian)
Vary: Accept-Language,Cookie,Accept-Encoding
Content-Language: de
Set-Cookie: csrftoken=edc8c77fc74f5e788c53488afba4e50a; Domain=www.deindeal.ch;
Max-Age=31449600; Path=/
Set-Cookie: generic_cookie=1; Path=/
Set-Cookie: sessionid=740a8a2cb9fb51166dcf865e35b91888; expires=Fri, 27-Jan-2012
13:15:00 GMT; Max-Age=2419200; Path=/
Location: http://www.deindeal.ch/welcome/?deal_slug=atlas-grand-hotel-2-naechte-
30-2
Content-Length: 0
Connection: close
Content-Type: text/html; charset=utf-8
Second request (with cookies):
So, I save the cookie using -c, check that it saves as cookie.txt, and run the request again with the addition of -b cookie.txt, getting this:
curl -i -b cookie.txt http://www.deindeal.ch/deals/atlas-grand-hotel-2-naechte-3
0-2/
HTTP/1.1 302 FOUND
Date: Fri, 30 Dec 2011 13:38:17 GMT
Server: Apache/2.2.16 (Debian)
Vary: Accept-Language,Cookie,Accept-Encoding
Content-Language: de
Set-Cookie: csrftoken=49f5c804d399f8581253630631692f5f; Domain=www.deindeal.ch; Max-Age=31449600; P
ath=/
Location: http://www.deindeal.ch/welcome/?deal_slug=atlas-grand-hotel-2-naechte-30-2
Content-Length: 0
Connection: close
Content-Type: text/html; charset=utf-8
To me this looks like exactly the same contents, minus one or two parameters in the cookie, but maybe I'm overlooking something?
I'm attempting to get the curl request to function and return the same contents as when requesting that url via a browser, but I'm not sure what I should do next.
Note: I've tagged this PHP, as I am using PHP to make the requests, I've simply using command line to easily show the returned headers - so if there's any other PHP libraries or methods that would work (better, or in a place that cURL wouldn't), please feel free to suggest any.
Any help would be greatly appreciated ;).
You need this,
curl -iL -c cookie.txt -b cookie.txt http://www.deindeal.ch/deals/atlas-grand-hotel-2-naechte-3
-b flag is used to read cookie from . For a file to be used to save cookie after the http transaction use -c flag. Its called cookie jar.
Using WebGet (Sorry, Its written by me) pulling the contents is quite simple.
require "WebGet.php";
$w = new WebGet();
$w->cookieFile = 'cookie.txt'; // must be writable
$w->requestContent("https://github.com/shiplu/dxtool");
print_r($w->responseHeaders) // prints response headers
print_r($w->cachedContent) // prints url content
I may be misunderstanding your question, but a 302 response means content found, and you just need to follow the "Location" right? cUrl will only perform one request, unlike your browser which will see that 302 (set the cookies, just like you're doing) then follow that location header. It looks like your location has a "?" in it that isn't in the original. Run cUrl, with that same cookie jar, on the Location url.
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_Redirection

Categories