How can I get both the GET and POST request params, on a POST request? - perl

I'm creating a facebook app with a Perl backend. The problem is that since Facebook sends the request to my web app as a POST request I'm having a problem getting the GET parameters that were also part of the base URL for the application -- in effect I'm only getting the POST params from $CGI->Vars.

See CGI/MIXING POST AND URL PARAMETERS.
Short version: use $CGI->param() for post paramenters and $CGI->url_param() for query string parameters.

Dump CGI in favour of a better interface. Plack's param method returns GET and POST parameters mixed.
plackup -MPlack::Request -e 'sub {
my ($env) = #_;
my $r = Plack::Request->new($env);
return [200, ["Content-Type" => "text/plain"], [join "\n", $r->param("foo")]];
}'
> lwp-request -m POST -USe 'http://localhost:5000/fnord?foo=bar;baz=quux'
Please enter content (application/x-www-form-urlencoded) to be POSTed:
foo=123;baz=456
␄
POST http://localhost:5000/fnord?foo=bar;baz=quux
User-Agent: lwp-request/6.03 libwww-perl/6.03
Content-Length: 16
Content-Type: application/x-www-form-urlencoded
200 OK
Date: Thu, 27 Oct 2011 21:27:46 GMT
Server: HTTP::Server::PSGI
Content-Length: 7
Content-Type: text/plain
Client-Date: Thu, 27 Oct 2011 21:27:46 GMT
Client-Peer: 127.0.0.1:5000
Client-Response-Num: 1
bar
123

Just set $CGI::APPEND_QUERY_STRING = 1;

Related

HTTP OPTIONS in Xamarin Forms

Getting "204 Status Code" as No Content
Here is a simple example of OPTIONS request:
var httpClient = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Options, new Uri("http://myapi.com"));
var response = await httpClient.SendAsync(request);
Just wondering why should you need to make one? OPTIONS is used to identify allowed request methods:
To find out which request methods a server supports, one can use curl
and issue an OPTIONS request:
curl -X OPTIONS http://example.org -i
The response then contains an Allow header with the allowed methods:
HTTP/1.1 200 OK
Allow: OPTIONS, GET, HEAD, POST
Cache-Control: max-age=604800
Date: Thu, 13 Oct 2016 11:45:00 GMT
Expires: Thu, 20 Oct 2016 11:45:00 GMT
Server: EOS (lax004/2813)
x-ec-custom-error: 1
Content-Length: 0
Source: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS

REST::Client | unable to parse GET response JSON object

This is the first time i am writing a Perl client to consume a REST service. I am using REST::Client and JSON perl module. The web service returns data in JSON format. The problem is when I try to use from_json or decode_json method on client->responseContent() method, I am getting an error saying
"malformed JSON string, neither array, object, number, string or atom, at character offset 0 (before "HTTP/1.1 200 \r\nCon..."
The web service is ofcourse a stable one and works fine with other languages REST clients.
After debugging the issue I found that client->responseContent() not only contains the JSON data but also the header information hence from_json is unable to parse it. Below is the snippet of the code:
my $url = "/data";
my $client = REST::Client->new();
$client->setHost($host);
my $headers = {Accept => 'application/json'};
$client->GET($url, $headers);
my $response = from_json($client->responseContent());
Not able to figure out this thing from two days now :-(
Here is the dump of "$client->{_res}->dump"
Fri Feb 23 09:38:35 2018: HTTP/0.9 200 EOF
Client-Date: Fri, 23 Feb 2018 09:38:35 GMT
Client-Peer: 45.32.84.105:8282
Client-Response-Num: 1
HTTP/1.1 200 \r
Content-Type: application/json;charset=UTF-8\r
Transfer-Encoding: chunked\r
Date: Fri, 23 Feb 2018 09:38:33 GMT\r
Connection: close\r
\r
2000\r
[{"REGION":"AP","REMARK":null,"STATUS":"PROD","UPDATED_TIME":null,"UPDATED_BY":null,"ROUTE_ID":1,"ROUTE_ID_VER":20150310,"USER_ROUTE_LOGIC":"|CAPTIVE|","USER_DEST":null,"USER_ORDSIZE_TYPE":null,"MIN_USER_ORDSIZE_VAL":0,"MAX_USER_ORDSIZE_VAL":100,"TAG_775":"|1|","CROSS_CURRENCY":"|Y|N|","TAG_12703":"|PB-CS|","COUNTRY":"|AU|HK|ID|IN|JP|KR|MY|SG|","TAG_12207":...
(+ 423449 more bytes not shown)
Even when the transfer encoding is not chunked, I am getting the same issue;
Fri Feb 23 10:40:20 2018: HTTP/1.1 200 ^M
Content-Type: application/json;charset=utf-8^M
Content-Length: 1618^M
Date: Fri, 23 Feb 2018 10:40:20 GMT^M
Connection: close^M
^M
{ "data":[ {
"REGION" : "AP",
"REMARK" : "",
"STATUS" : "PROD",
"UPDATED_TIME" : "",
"UPDATED_BY" : "",
Ultimately, solved using curl command for now (Actual code snippet below):
my $command = "curl '$url'";
my $rules = qx/$command/;
I have a similar issue that I am working through. I suspect (Have not verified yet) that the root cause is that the server is not passing the Encoding-Content Response Header, therefore LWP::UserAgent and HTTP::Response are not attempting to return the decoded string. I am going to try to isolate where this decision is being made and see what options are available and request a patch.
Perl REST::Client - Garbage data in response

Google oAuth2 unauthorized_client by refresh_token

i'm trying to use an refresh token from the oAuth2 web redirect auth in my console perl script. The client id is the same and correct client id i used in my javascript an i checked it 5 times that it ist the same as i have in my google API's Console.
The client secret is checked two and it is correct.
The refresh token was created with approval_prompt=force&access_type=offline
Here is my perl sample code i use:
# -----------------------------------------------------------------------------------
my $CLIENT_ID = 'XXXXX.apps.googleusercontent.com';
my $CLIENT_SECRET = 'YYYYYYYYYYY';
# -----------------------------------------------------------------------------------
# TESTING
my $refresh_token = '1/is_5_minutes_old';
# -----------------------------------------------------------------------------------
my $string = '';
$string .= 'grant_type=refresh_token';
$string .= '&client_id=' . $CLIENT_ID;
$string .= '&client_secret=' . $CLIENT_SECRET;
$string .= '&refresh_token=' . $refresh_token;
$ua = LWP::UserAgent->new;
my $req =
HTTP::Request->new( POST => 'https://accounts.google.com/o/oauth2/token' );
$req->content_type('application/x-www-form-urlencoded');
$req->content($string);
print $string . "\n";
my $res = $ua->request($req);
print $res->as_string;
The response of it:
HTTP/1.1 400 Bad Request
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: close
Date: Mon, 02 Sep 2013 10:50:26 GMT
Pragma: no-cache
Server: GSE
Content-Type: application/json
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Alternate-Protocol: 443:quic
Client-Date: Mon, 02 Sep 2013 10:50:26 GMT
Client-Peer: 74.125.136.84:443
Client-Response-Num: 1
Client-SSL-Cert-Issuer: /C=US/O=Google Inc/CN=Google Internet Authority G2
Client-SSL-Cert-Subject: /C=US/ST=California/L=Mountain View/O=Google Inc/CN=accounts.google.com
Client-SSL-Cipher: RC4-SHA
Client-SSL-Warning: Peer certificate not verified
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
{
"error" : "unauthorized_client"
}
i hope you have an idea to help.
greatings
Invalid client usually means that the client ID and client secret don't match, or there is a typo in one of them (though you mention you've double checked this!). Nothing in your code looks wrong.
When you retrieve the refresh token, could you try putting the access token that comes along with it into the tokeinfo endpoint and making sure the values for client ID there match the ones you've configured with: https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=
It might be worth dumping out the request to make sure there isn't a mistake in that (e.g. too short a content-length header or similar).
Dumping the request is key. To help , here is one I baked earlier..
==POST==
https://accounts.google.com/o/oauth2/token
refresh_token=1/_PEzU2m71wertwertwerJUtrtrytrytryf3trytryoCo
&client_id=612222222225
&client_secret=Q7334534543534yKLu
&grant_type=refresh_token
Are you using the short form of the client id, ie. just the number?

Having Get single and Get all methods on a ApiController

I'm developing an API using close to the latest bits from the aspnetwebstack Codeplex project (4592e2f63c55 from 2012-05-09 if anyone is interested).
I have the following route:
context.Routes.MapHttpRoute("SiteSpecific", "Api/{controller}/{customerId}/{siteToken}/{id}",
new { id = UrlParameter.Optional });
And what I'm currently trying to do is implement get single and a get all in an ApiController. The Get all method, for testing is the following:
public IEnumerable<EditChatResponse> Get(string customerId, string siteToken)
{
return new []{new EditChatResponse{Template = "Get All"}, };
}
And the get single is currently following:
public EditChatResponse Get(string customerId, string siteToken, string id)
{
return new EditChatResponse {Template = "Get Single"};
}
However, routing is always choosing the Get single method:
$ curl -i -H "Accept: applicaiton/json" http://localhost/api/chatresponse/a/b
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Mon, 14 May 2012 18:06:26 GMT
Content-Length: 66
{"Id":0,"Template":"Get Single","Inherited":false,"Enabled":false}
$ curl -i -H "Accept: applicaiton/json" http://localhost/api/chatresponse/a/b/c
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Mon, 14 May 2012 18:06:28 GMT
Content-Length: 66
{"Id":0,"Template":"Get Single","Inherited":false,"Enabled":false}
I've tried renaming the Get all method to GetAll, as I've seen in some examples, decorating it with [HttpGet], but it still chooses the single method.
Am I completely missing something, or do I need to go about this a different way (most of the examples I see look to be related to the beta bits, and not a recent version from CodePlex)?
Try using this for the default id parameter:
new { id = System.Web.Http.RouteParameter.Optional }

adding a response header to 302 response using perl

i am trying to write a perl page that returns an http 302 response to a different location and adds a custom header to that response.
so my desired http response should be something like this:
HTTP/1.1 302 Moved
Date: Sun, 15 Apr 2012 10:59:02 GMT
Server: Apache
Location: http://www.google.com
Content-Length: 396
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=iso-8859-1
CUSTOM_HEADER: CUSTOM_VALUE
i tried using CGI:
#!/bin/perl
use strict;
use APR::Request::Apache2;
my $r = shift;
$r->content_type('text/html; charset=utf-8');
$r->headers_out()->add("CUSTOM_HEADER", "CUSTOM_VALUE");
$r->headers_out()->add("Location", "http://www.google.com");
$r->status(302);
and i do get 302 response to google but no CUSTOM_HEADER. once i change the status to 200 by $r->status(200); i do get the CUSTOM_HEADER.
so whats up with this behavior ? how can i add my header to the 302 response ?
Use $r->err_headers_out->set or $r->err_headers_out->add
my $r = shift;
$r->content_type('text/html; charset=utf-8');
$r->err_headers_out->set(Location => "http://www.google.com");
$r->status(302);
You should use err_headers_out(). These will be printed even on errors and redirects.