PHP Curl CURLOPT_POSTFIELDS alternative for node.js - php

I'm looking for a way to interact with a form before submitting a POST like the CURLOPT_POSTFIELDS option for PHP curl provides, but with node.js.
I'm rewriting some PHP code to javascript, and it's the following line I can't find a javascript alternative for
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"rememberMe": true}');
I'm currently using the node-fetch NPM library
My javascript code so far
fetch(requestUrl,
{
method: 'POST',
headers: headers,
}
)
with the headers including content-type and authorization

Thanks to #tadman the answer was found at https://www.npmjs.com/package/node-fetch#post-with-json
By providing a body you can achieve the desired result
Final code would look like the following if JSON is the desired way to go
fetch(requestUrl,
{
method: 'POST',
body: JSON.stringify({'rememberMe': 'true'}),
headers: headers
}
)

Related

How do I get HTML back from a cURL in PHP vs. an actual link?

I am new to cURL.
When I make the following GET in jquery/ajax, I receive HTML in the response that creates a popup login window (oauth2).
When I use the following code in a backend php script to hit the same endpoint, I get back a clickable link...which, when clicked takes you to a login page.
What am I missing?
The PHP
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "https://oauthserverxxx.com//login/oauth2/auth?client_id=11111&response_type=code&scope=/auth/userinfo&redirect_uri=http://localhost/oauth_complete.php");
$result = curl_exec($curl);
Response from cURL
You are being redirected.bool(true)
1
The AJAX/jquery
$.ajax({
type: "GET",
url: "https://client.instructure.com//login/oauth2/auth?client_id=6666&response_type=code&redirect_uri=http://oauth_complete.php",
// dataType: 'html',
processData: true,
success: function(canvasAuthHTML) {
$('#flexModalHeader').html('Login...');
$('#flexModalMsg').html(canvasAuthHTML);
$('#flexModal').modal('show');
console.log('Called Canvas - response: ' + canvasTok);
},
error: function (data) {
console.log('Fail - could not get LTI auth token...');
chrome.runtime.sendMessage({ msg: "oauthLTI", token: "failed"});
}
});
Response
This will pop the login form inside the modal - the response from the server is detailed HTML.
could be several things,
first off, the jQuery request probably uses an pre-existing cookie session, your curl request doesn't have any cookies.
second, the jQuery request follows "Location" http-header-redirects, your curl code doesn't, but if that is the problem, you can instruct curl to do the same by setting CURLOPT_FOLLOWLOCATION to 1.
third, the jQuery request has an user-agent string, your curl request does not (libcurl has no default user-agent. the curl cli program does, but libcurl, which you use through php's curl_ functions, doesn't.), some websites block requests with no user-agent. if that's the problem, you can simply copy jQuery's user-agent string and tell curl to use it with CURLOPT_USERAGENT
fourth, by default, most browsers use compression where possible, but your curl request doesn't support compression. it's unlikely, but possible, that the server handles curl's request differently because it doesn't support compressed transfers, if that's the problem, you can enable compression in your curl request by setting CURLOPT_ENCODING to emptystring (that will enable all compressions that libcurl was compiled with, which is usually gzip and deflate) - actually, i recommend doing this regardless, because you're fetching HTML, which compresses really well, so unless your cpu is really slow, it will also make the code execute faster. that's the same reason browsers do it by default.
.- the most reliable way to find the culprit, is to record both requests, compare them side by side, and take away every single difference in the 2 requests, 1 by 1, until the requests are identical. sooner or later, you'll find the difference that made the server respond differently (and my best guess here is a location redirect), for that, i recommend the program FiddlerProxy

When to use header('Content-Type: application/json') in PHP

I've been trying to figure out what's really the usage of header('Content-Type: application/json') in php scripts and I've found different questions and answers on stackoverflow about this subject but I still don't completely get it...
So here's the question : I've seen in some php projects this line of code, and I'm trying to understand
if this is used when another web page is calling this actual script (with ajax for example) so that the calling page can get a json from the php page
OR
if this script means that the php page is going to deal with json sent from another web page. Or maybe something else ???
Another thing that could help me if answered, lately I've been retrieving json from a resource (external url) with cURL and I had to put this header (Content-type:application/json) in the request. Did I send this header to the exertnal resource or was this MY header so that I can deal with the returned json ?
thanks
Ok for those who are interested, I finally figured out that header('Content-Type: application/json') is used when another page is calling the php script, so that the other page can automatically parse the result as json.
For instance i have in my test.php :
header('Content-type: application/json; charset=utf-8');
$arr = array ('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5);
echo json_encode($arr); // {"a":1,"b":2,"c":3,"d":4,"e":5}
and in my main.js
function test() {
$.ajax({
url: 'test.php',
type: 'GET',
//dataType: 'html',
success: function (response) {
alert(response);
}
});
};
When I dont have dataType set to "json" or when I don't have the header in my test.php, the alert gives {"a":1,"b":2,"c":3,"d":4,"e":5} which is a string (tried with typeof(response), and when I have this header, or dataType:"json", I get [object Object] from the alert. So this header function is there to indicate to the calling pages which type of data it gives back, so that you can know how to deal with it. In my script, if I didn't have header('Content-Type: application/json'), I would have to parse the response in the javascript like this : JSON.parse(response) in order to make it a json, but with that header, I already have a json object, and I can parse it to html with jSON.stringify(response).
You should always set the Content-Type for any HTTP response to describe what you're serving in that response.
Whether it's JSON or something else, and whether it's for an AJAX request or any other kind of request.
You should also set the Content-Type for any request to describe your POST payload.
In PHP, if you don't specify the Content-Type header in the script, it will default to whatever you've configured default-mimetype to be in your php.ini file which is usually text/html.
Calling header('Content-Type: application/json') will override that default setting so that the script will respond with that Content-Type when requested.
Also, when calling curl with a Content-type:application/json header, you're specifying the content type for your request body and not for the expected reponse.
W3 Description For the Content-Type
The purpose of the Content-Type field is to describe the data contained in the body fully enough that the receiving user agent can pick an appropriate agent or mechanism to present the data to the user, or otherwise deal with the data in an appropriate manner.
Shortly speaking, just to inform the receiver what kind of data he received and consume it accordingly.

Laravel doesn't read HTTP request payload for PUT request

So I am stumbling a bit here, as I have figured out that PHP will not read the HTTP request body from a PUT request. And when the Content-Type header in the request is set to application/json, there doesn't seem to be any way to get the body.
I am using Laravel, which builds their request layer on top of Symfony2's HttpFoundation lib.
I have debugged this a bit with jQuery, and these are some example requests:
Doing a request like this, I can find the content through Input::getContent()
$.ajax({
url: 'http://api.host/profiles/12?access_token=abcdef',
type: 'PUT',
data: {"profiles":[{"name":"yolanda ellis","email":"yolanda.ellis12#example.com"}]}
});
I cannot get the content with file_get_contents('php://input') though. jQuery per default sends the data as application/x-www-form-urlencoded.
It becomes even more mindboggeling when I pass another Content-Type in the request. Just like Ember-Data does:
$.ajax({
url: 'http://api.host/profiles/12?access_token=abcdef',
type: 'PUT',
data: {"profiles":[{"name":"yolanda ellis","email":"yolanda.ellis12#example.com"}]},
contentType: 'application/json'
});
The data seems nowhere to be found, when doing it like this. This means that my Ember.js app does not properly work with my API.
What on earth is going on here?
Edit
Here's a full request example as seen in Chrome DevTools: http://pastebin.com/ZEjDAsmJ
I have found that this is a Laravel specific issue.
Edit 2: Answer found
It appears that there's a dependency in my project, which reads from php://input when the Content-Type: application/json header is sent with the request. This clears the stream—as pointed out in the link provided by #Mark_1—causing it to be empty when it reaches Laravel.
The dependency is bshaffer/oauth2-server-php
You should be able to use Input::json() in your code to get the json decoded content.
I think you can only read the input stream once, so if a different package read the input stream before you, you can't access it.
Are you using OAuth2\Request::createFromGlobals() to create the request to handle your token? You should pass in the existing request object from Laravel, so both have access to the content.
Did you read this? http://bshaffer.github.io/oauth2-server-php-docs/cookbook/laravel/
That links to https://github.com/bshaffer/oauth2-server-httpfoundation-bridge which explains how to create a request object from an httpfoundation request object (which Laravel uses).
Something like this:
$bridgeRequest = \OAuth2\HttpFoundationBridge\Request::createFromRequest($request);
$server->grantAccessToken($bridgeRequest, $response);
So they both share the same content etc.
I found the following comment at http://php.net/manual/en/features.file-upload.put-method.php
PUT raw data comes in php://input, and you have to use fopen() and
fread() to get the content. file_get_contents() is useless.
Does this help?

Detect an ajax request

I'm writing my own MVC framework to practice and I have a Request class. I would like to catch the type of request and parse data accordingly whether its an AJAX/JSON call or a HTML/XML request.
Im currently using:
$_SERVER['HTTP_ACCEPT']
and above when used var_dump on it returns application/json for this:
$.ajax({
type: 'post',
url: 'index',
dataType: 'json',
data: {
_method: 'put'
}
});
var_dump($_SERVER['HTTP_ACCEPT']) returns:
string(46) "application/json, text/javascript, */*; q=0.01"
Question:
is this method reliable? Does it work always? Are there any security problems with detecting ajax call like this?
Note that all my ajax calls in my framework must have dataType: 'json' unless its a different type of call like HTML or XML.
Using jQuery, you can use $_SERVER['HTTP_X_REQUESTED_WITH'] which will be set to "XMLHttpRequest." This is the most reliable method when using jQuery.
Colin Morelli answered your main question, but this should help you with your follow ups.
XMLHttpRequest means its an ajax call? How would I detect the type if
its XML or JSON
Yes. XMLHttpRequest is JavaScript object that makes the request. It's poorly named now, though, because you can have it send whatever you want. To answer your second question you'll have to do some sort of parsing attempt on the payload you receive. You can scan for XML and if not found just assume it's JSON and attempt to parse.

Need assistance with cURL. Need to replace ajax call

My client wants me to implement a page. On this page I made an API call using AJAX (as shown in code).
jQuery.ajax({
url: endpoint,
type: "POST",
cache:false,
data: {
url:"link-rest/sweepstakes/claim",
userId:193298,
prizeRank:2,
sweepStakeId:186
},
dataType: "json",
headers: {
Authorization:token
},
success: function(json){
callback(json);
},
error: function(xhr, status, error){
callback(errorHandle(2));
}
});
But now he wants to use this page for SEO aswell. For that I have to make an API call in php. I have never worked with cURL before. And the examples on stackoverflow does not seem to work for me. I have Wamp Server installed and the php_curl extension has been activated. All services for wamp have also been restarted. This is what I tried to implement.
$json_url = 'link-rest/sweepstakes/claim&userId=193298&prizeRank=2&sweepStakeId=186&Authorization=ams0TGpFek5EazBNekExTmprd01EYz1NVGt6TQ';
$ch = curl_init($json_url);
$options = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => array('Content-type: application/json'),
);
curl_setopt_array($ch, $options);
$result = curl_exec($ch);
var_dump(json_decode($result));
But all that is printed on my screen is "null". Can anyone please tell me what I am doing wrong here?
The basic problem with the code is that you are using a relative URI and not an absolute one.
You also seem to be trying to provide a request encoded in JSON, but the Ajax appears to use standard form encoding and only expects JSON in the response
A more fundamental problem is that you are using cURL in the first place. link-rest/sweepstakes/claim is presumably handled via PHP, so you should refactor out the bits you want to call into a library and then call that library from the function you are writing. (While turning the page that handles the Ajax request into a simple View around it).

Categories