I'm trying to replace RSS polling with PubSubHubbub on my site. I'm able to use the subscriber library that google offers to send the subscription request. From the code it looks like it sends a post request via cURL with the RSS URL and a callback URL.
So this is where I need some direction:
In order to complete the subscription request my callback URL has to receive a GET request and then echo back a value from the GET request along with a 200 response. How do I get the parameters from the GET request? Is the echo done again via cURL? If so what option should include the 200 response?
This very simple script should be a start:
echo $_GET["request_name"];
this will output the GET parameter request_name and (implicitly) send a 200.
It's also a good idea to explicitly declare a content type before echoing, to prevent the default content type (usually "text/html") from kicking in:
header("Content-type: text/plain");
Note that when echoing external data, you may need to sanitize the output first - if the for example the output format is HTML, you would want to do something like echo htmlspecialchars($_GET["request_name"]); to prevent Cross-Site Scripting.
There was recently a thread on the php-dev mailing list about this. The reason you can't access 'hub.challenge' in the $_GET superglobal is due to register_globals. Basically PHP cleans up any argument names before creating the superglobals. Any dots will be converted to underscores. It's looking to be 'fixed' in PHP 6, but not before due to BC issues.
Here's the thread about it.
Related
I'm trying to integrate a virtual paying system from a bank into my website.
The bank system makes an asynchronous HTTP call to a URL that I define (a PHP document), and from there I try to get the order ID and mark the order as paid.
The problem I'm facing, is that with only the HTTP call I don't seem to be able to get this ID parameter, as the expected result (the couchdb documnt is marked as payed) is not there.
But, when I browse to my document and I paste after it the content of the HTTP call, then it works, like so:
http://example.com/crud.php?Ds_SignatureVersion=xxx&Ds_MerchantParameters=xxx&Ds_Signature=xxx
On my crud.php I do the following:
$test = $_GET['Ds_MerchantParameters'];
Why am I managing to get this parameter when I browse to the URL, but not when the bank system makes the HTTP POST call?
If the bank system issues a POST request to your site, the passed parameters are not in $_GET, but in $_POST. So change
$test = $_GET['Ds_MerchantParameters'];
to
$test = $_POST['Ds_MerchantParameters'];
If you want to be able to use both GET and POST requests for the page, you can also use $_REQUEST:
$test = $_REQUEST['Ds_MerchantParameters'];
Introduction
I've read the following:
Hypertext Transfer Protocol (HTTP) is the life of the web. It's used every time you transfer a document, or make an AJAX request. But HTTP is surprisingly a relative unknown among some web developers.
The HTTP verbs comprise a major portion of our “uniform interface” constraint and provide us the action counterpart to the noun-based resource. The primary or most-commonly-used HTTP verbs (or methods, as they are properly called) are POST, GET, PUT, and DELETE.
Huh?
Well, we came to the point I lost track of things.
PUT and DELETE, they say. I've only ever heard of POST and GET and never saw something like $_PUT or $_DELETE passing by in any PHP code I've ever viewed.
My question
What are these methods (PUT) and (DELETE) for and if it's possible to use them in PHP, how would I go about this.
Note: I know this is not really a problem but I always grab a learning opportunity if I see one and would very much like to learn to use these methods in PHP if this is possible.
What are these methods (PUT) and (DELETE) for...
There are a lot of words to spend to explain this, and I'm not skilled enough to do it, but as already posted, a quick recap of what the HTTP specification describes.
The protocol basically says this:
use GET when you need to access a resource and retrieve data, and you don't have to modify or alter the state of this data.
use POST when you need to send some data to the server. Ex. from a form to save these data somewhere.
use HEAD when you need to access a resource and retrieve just the Headers from the response, without any resource data.
use PUT when you need to replace the state of some data already existing on that system.
use DELETE when you need to delete a resource (relative to the URI you've sent) on that system.
use OPTIONS when you need to get the communication options from a resource, so for checking allowed methods for that resource. Ex. we use it for CORS request and permissions rules.
You can read about the remaining two methods on that document, sorry I've never used it.
Basically a protocol is a set of rules you should use from your application to adhere to it.
... and if it's possible to
use them in PHP, how would I go about this.
From your php application you can retrieve which method was used by looking into the super global array $_SERVER and check the value of the field REQUEST_METHOD.
So from your php application you're now able to recognize if this is a DELETE or a PUT request, ex. $_SERVER['REQUEST_METHOD'] === 'DELETE' or $_SERVER['REQUEST_METHOD'] === 'PUT'.
* Please be also aware that some applications dealing with browsers that don't support PUT or DELETE methods use the following trick, a hidden field from the html form with the verb specified in its value attribute, ex.:
<input name="_method" type="hidden" value="delete" />
Follow an example with a small description on a possible way to handle those 2 http requests
When you (your browser, your client) request a resource to an HTTP server you must use one of the method that the protocol (HTTP) accepts. So your request needs to pass:
A METHOD
An Uri of the resource
Request Headers, like User-Agent, Host, Content-Length, etc
(Optional body of the request)
Now, while you would be able to get data from POST and GET requests with the respective globals ($_GET, $_POST), in case of PUT and DELETE requests PHP doesn't provide these fast access globals; But you can use the value of $_SERVER['REQUEST_METHOD'] to check the method in the request and handle your logic consequently.
So a PUT request would look like:
PUT /something/index.php
(body) maybe=aparameter
and you can access those data in PHP by reading the php://input stream, ex. with something like:
if ($_SERVER['REQUEST_METHOD'] === 'PUT') {
$myEntireBody = file_get_contents('php://input'); //Be aware that the stream can only be read once
}
and a DELETE request would look like:
DELETE /something/index.php?maybe=aparameter
and again you can build your logic after have checked the method:
if ($_SERVER['REQUEST_METHOD'] === 'DELETE') {
// do something
}
Please pay attention that a DELETE request has no Body and pay very attention to Response Status Code too (ex. if you received a PUT request and you've updated that resource without error you should return a 204 status -No content-).
Way to use PUT data from PHP:
$method = $_SERVER['REQUEST_METHOD'];
if ('PUT' === $method) {
parse_str(file_get_contents('php://input'), $_PUT);
var_dump($_PUT); //$_PUT contains put fields
}
PHP's $_GET and $_POST are poorly named. $_GET is used to access the values of query string parameters, and $_POST lets you access the request body.
Using query string parameters is not limited to GET requests, and other kinds of requests than just POST can come with a request body.
If you want to find out the verb used to request the page, use $_SERVER['REQUEST_METHOD'].
Most suitable place to use these (PUT and DELETE) methods is REST API. Where we use http methods to define the mode of operation for example you want to fetch any resources then you can use following:
GET http://api.example.com/employee/<any_id>
to add a new item:
POST http://api.example.com/employee/
to Update or Edit:
PUT http://api.example.com/employee/
to Delete an existing resource:
DELETE http://api.example.com/employee/1
etc.
Now on PHP side you just need to read what HTTP method used so that you can make an action according to that.
There are lots of libraries available which can do that for you.
What are these methods (PUT) and (DELETE)
There are described in the HTTP spec.
In a nutshell, and simplifying somewhat, PUT is for uploading a file to a URL and DELETE is for deleting a file from a URL.
never sawy something like $_PUT or $_DELETE passing by in any PHP code I've ever viewed
$_POST and $_GET are terribly named superglobals. $_POST is for data parsed from the request body. $_GET is for data parsed from the URL. There's nothing that strictly ties data in either of those places (especially the URL) to a particular request method.
DELETE requests only care about the URL's path, so there is no data to parse.
PUT requests usually care about the entire request body (not a parsed version of it) which you would access with file_get_contents('php://input');.
for and if it's possible to use them in PHP, how would I go about this.
You'd need to map the URL onto a PHP script (e.g. with URL rewriting), test the request method, work out what URL you were actually dealing with, and then write code to do the appropriate action.
$GLOBALS["_PUT"]=null;
if($_SERVER['REQUEST_METHOD'] == 'PUT') {
$form_data= json_encode(file_get_contents("php://input"));
$key_size=52;
$key=substr($form_data, 1, $key_size);
$acc_params=explode($key,$form_data);
array_shift($acc_params);
array_pop($acc_params);
foreach ($acc_params as $item){
$start_key=' name=\"';
$end_key='\"\r\n\r\n';
$start_key_pos=strpos($item,$start_key)+strlen($start_key);
$end_key_pos=strpos($item,$end_key);
$key=substr($item, $start_key_pos, ($end_key_pos-$start_key_pos));
$end_value='\r\n';
$value=substr($item, $end_key_pos+strlen($end_key), -strlen($end_value));
$_PUT[$key]=$value;
}
$GLOBALS["_PUT"]=$_PUT;
}
if (!function_exists("getParameter")){
function getParameter($parameter)
{
$value=null;
if(($_SERVER['REQUEST_METHOD'] == 'POST')&& (isset($_POST[$parameter]))){
$value=$_POST[$parameter];
}
else if(($_SERVER['REQUEST_METHOD'] == 'PUT')&& (isset($GLOBALS["_PUT"][$parameter])))
{
$value=$GLOBALS["_PUT"][$parameter];
}
else if(($_SERVER['REQUEST_METHOD'] == 'DELETE')&& (isset($_DELETE[$parameter]))){
$value=$_DELETE[$parameter];
}
else if(($_SERVER['REQUEST_METHOD'] == 'PATCH')&& (isset($_PATCH[$parameter]))){
$value=$_PATCH[$parameter];
}
else if(isset($_GET[$parameter])){
$value=$_GET[$parameter];
}
return $value;
}
}
I tryied searching for this and I belive I alredy know the answer but it's crusal that I'm not wrong, so here I go..
When calling get_headers, will I retrieve the whole file even though the function only returns the headers or will it retrieve, as expected, only the headers and nothing else?
I'm guessing the last but if I'm wrong this will cause some serious problems..
Also I noticed that there is a global setting I can change to send a HEAD request instead of the default GET request, witch is why I'm asking my self whats really going on.
Edit
Maybe this function is a better alternative? stream_get_meta_data or do they actually do the same thing?
You could also take a look at the source code, if you are familiar with C.
The function is defined here. I quickly looked over this, and it seems it is a header-only request, see line 715:
STREAM_ONLY_GET_HEADERS
GET
Requests a representation of the specified resource. Requests using
GET should only retrieve data and should have no other effect. (This
is also true of some other HTTP methods.) The W3C has published
guidance principles on this distinction, saying, "Web application
design should be informed by the above principles, but also by the
relevant limitations."
HEAD
Asks for the response identical to the one that would correspond to a
GET request, but without the response body. This is useful for
retrieving meta-information written in response headers, without
having to transport the entire content.
Wikipedia/Hypertext_Transfer_Protocol
The PHP-docs clearly states that normal get_headers() uses a GET-request, but you can force it to use HEAD instead, like this:
<?php
// By default get_headers uses a GET request to fetch the headers. If you
// want to send a HEAD request instead, you can do so using a stream context:
stream_context_set_default(
array(
'http' => array(
'method' => 'HEAD'
)
)
);
$headers = get_headers('http://example.com');
?>
Unfortunaley you're right, just read the PHP manual:
get_headers() returns an array with the headers sent by the server in response to a HTTP request.
Also take a look at the examples.
Okay, next time I should spend more attention to the question formulation.
Yeh, if the request type is set to GET (standard) you will get the whole content. You could change it to HEAD, but this is not what you want.
Tamper Data gives all the cookie context i wish to automate that. Session-Id and Login Credentials.
WGET or Wapiti kinda stuff.. but these are cmnd line based ..
i wish a web-based one ! the Tamper data values i need to pass are under the red box of screenshot.
Relying on the request-header's values is dicey and it is flawed since the request-header values can be easily manipulated (one example is what you yourself are showing).
If you want to login automatically into another web-application using the credentials you have provided in some other web-application then you can use Single Sign-on (SSO). More info can be found in this answer.
If you have some other requirement, then you can included that in the question so that it can be seen & answered accordingly.
Here is how you can get the request-header in a JSP:
request.getHeader("cookie") or request.getHeader("user-agent").
Or can use: request.getHeaderNames() to get all the headers and then loop through the names and get each header value by using point#1 like this:
Enumeration hNames = request.getHeaderNames();
while(hNames.hasMoreElements()) {
String hName = (String) hNames.nextElement();
System.out.println(hName + " = " + request.getHeader(hName);
}
This link might be helpful: Reading HTTP Request Headers
Here is how you can get the request headers in PHP:
Nice answer to the question: How do I read any request header in PHP,
I'm currently developing a Restful Json-API in PHP. I want to send a PUT-Request to items/:id to update a record. The data will be transferred as application/json.
I want to call the API with
curl -H "Content-Type: application/json" -X PUT -d '{"example" : "data"}' "http://localhost/items/someid"
On the server side, I'm not able the retrieve the request body. I tried
file_get_contents("php://input");
but this returns an empty string. Also a fopen()/fread() combination doesn't work.
When calling via POST, everything works great, I can read the json perfectly on the server side. But the API isn't Restful anymore. Does anyone have a solution for this? Is there another way to send and receive Json?
btw, I'm developing the API with the Slim Framework.
php://input is only readable once for PUT requests:
Note: A stream opened with php://input can only be read once; the stream does not support seek operations. However, depending on the SAPI implementation, it may be possible to open another php://input stream and restart reading. This is only possible if the request body data has been saved. Typically, this is the case for POST requests, but not other request methods, such as PUT or PROPFIND.
http://php.net/manual/en/wrappers.php.php
The Slim framework already reads the data upon request. Take the data from the Request object, into which it has been read.
On the server side, I'm not able the retrieve the request body. I tried file_get_contents("php://input");
You can only use file_get_contents( 'php://input', 'r' ); once per request. Retrieving its values will truncate the values as well, so if you call it twice, it'll return an empty string. Slim's request object contains the values you need, so:
<?php
$app = new Slim( );
$app->put( '/items/someid', function () use ( $app ) {
echo $app->request( )->put( 'example' ); // should display "data".
});
The example from the PHP manual uses fopen to access php://input in read mode. Have you tried doing it that way instead?
EDIT: The manual page for PHP:// says some stuff that seems to suggest that PUT data might not be available in some cases!
Note: A stream opened with php://input can only be read once; the
stream does not support seek operations. However, depending on the
SAPI implementation, it may be possible to open another php://input
stream and restart reading. This is only possible if the request body
data has been saved. Typically, this is the case for POST requests,
but not other request methods, such as PUT or PROPFIND.
I don't know where this will leave you regarding PUT processing. One page seems to say it's possible, the other seems to imply that it won't work under the wrong set of circumstances
I was reading the SLIM framework documentation the other day and it said that some browsers have problems with PUT and DELETE.
Excerpt:
Unfortunately, modern browsers do not provide native support for PUT requests. To work around this limitation, ensure your HTML form’s method is “post”, then add a method override parameter to your HTML form like this:
<form action="/books/1" method="post">
... other form fields here...
<input type="hidden" name="_METHOD" value="PUT"/>
<input type="submit" value="Update Book"/>
</form>
Source: http://www.slimframework.com/documentation/stable