Confusion in Angular 2 Http Post Request - php

First of all. Please bear with my questions.
What I am doing is just performing an ajax request which will return a response data of string.
Here's my php
<?php
header('Access-Control-Allow-Origin: *');
echo 'Peenoise Crazy';
?>
Http request
let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
let options = new RequestOptions({ headers: headers });
return this.http.post('./app/parsers/peenoise.php', '', options)
.then(val => console.log(val))
This doesn't work. But if I change the url into this http://localhost:8912/app/parsers/peenoise.php. It works.
Questions
Why ./app/parsers/peenoise.php doesn't work?
If I change the url to http://localhost:8912/app/parsers/peenoise.php. Why do I need to put header('Access-Control-Allow-Origin: *')? It is on the same folder of my app.
How to use http.post without passing an url of http://localhost:8912/route/to/phpfolder.php?
Any help would be appreciated. Please guide me to this. Thanks

Post requires a full or a relative URL to work. You can use:
this.http.post('/parsers/peenoise.php', '', options)

Actually Angular looks for a backend server to post the data, so Imagine in your post request is like below
this.http.post('./app/parsers/peenoise.php', '', options).then(val => console.log(val))
It will try to make the post request at the location
imagine you are serving angular on localhost:4200
http://localhost:4200/app/parsers/peenoise.php
Now to answer your Questions :
1)./app/parsers/peenoise.php doesn't work because it's actually trying to find it from your backend service
2)You need to put header('Access-Control-Allow-Origin: *') whenever you are making an http request to a different server than from the one which your site is currently using, if you don't use that you'll end up with Connection_refused_Error.
3)If you want to use just angular then there are mockAckends, in-memory-web-api
An example using mockBackEnd is
here

Related

Sending multipart/form-data with PUT request doesn't work in Laravel

I am trying to send an HTTP PUT request with "Content-Type": "multipart/form-data" to a Laravel application. When I change the method to POST it works.
$a = $request->all(); // With PUT this is empty but with POST it works fine.
The client-side executes the following code:
axios({
method: "post", // when I try method:"PUT" and change the content type
url: "/api/offer",
data: fd,
headers: {"Content-Type": "multipart/form-data"} // here change to "x-www-form-urlencoded" it the $a array on backend is empty!
}).then(response => {
console.log("/offer/" + response.data)
if (response.data)
window.location.replace("/offer/" + this.offer.id);
else {
console.log("show a message that something went wrong! ")
}
}).catch(function (error) {
})
I could not find anywhere in the docs that PUT can't send "multipart/form-data"
So, can PUT send "multipart/form-data" or only POST can do that in general or it is only a PHP / Laravel Issue?
Edit:
Also, what difference does it make to use PUT instead of POST other than to comply with HTTP protocol and CRUD operation properly?
Laravel (HTML Forms) do not work great with Put requests so you'll need to spoof a POST request as if it was a PUT or PATCH request. On Axios you use the .post verb but within your form data you append
_method: "put"
Information from the official documentation:
https://laravel.com/docs/8.x/routing#form-method-spoofing
Excerpt from the documentation:
HTML forms do not support PUT, PATCH, or DELETE actions. So, when defining PUT, PATCH, or DELETE routes that are called from an HTML form, you will need to add a hidden _method field to the form. The value sent with the _method field will be used as the HTTP request method
I ran into this issue a few weeks ago myself with a Symfony 5.3 project. It only worked with POST Requests, not with PUT. Here's an issue from the Symfony GitHub that explains it in more detail.
To my understanding the issues lies within the PHP implementation of those requests. The HTTP standard "PUT" supports it, but PHP does not. Here's also a link to the bug from the PHP bugtracker.

Cross Origin $http Requests | Resource

So I was writing an app when I got across this issue.
This is the PHP : Slimframework Corresponding :
$app->delete('/products/:id',function($id) use($app){
$db = new mysqli('notsocoolhost','verycooluser','verycoolpassword','verycooldatabase');
$db->query("DELETE from products WHERE id='$id'");
});
I removed the part where I confirm that you can actually delete it from the database.
This is Angular.JS :
$scope.del = function(product){
$http({
method: "DELETE",
url: baseUrl + product.id
}).success(function(){ ...... //Returns 0 -> WTF?
This buddy here returns in error status : 0
and this one below returns 405:
$scope.delete(baseUrl + product.id).success ... //Returns 405 : Method Not Allowed
To sum it up, I added couple of tests on Hurl.it and the RESTApi from Slimframework is fully functioning. which leaves it as Angular.js problem ? I guess?
UPDATE:
After further inspection I've revealed the following:
1) Mysteriously the : Request Method (Field by Firefox) is OPTIONS.
2) Access-Control-Request-Method : "DELETE"
3) Access-Control-Allow-Methods: "GET,POST,DELETE,PUT"
I hope this serves people in the future.
Back to basics, having trouble sending $http requests in cross-origin requests has nothing to do with the server nor Angular.js.
If you are like me hosting your webapp on:
https:\\www.beautifuldomain.com
and your API on :
https:\\api.beautifuldomain.com
Whenever you try to perform a request between Webapp and API you are performing Cross-Origin Request.
What does it mean?
It means that your message will be considered as Cross-Origin and it will be preflighted.
Preflighted?
It means that when you use any method other than GET,HEAD or POST.
Also POST if used to send request data with Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain, e.g.
It will be sent as method: OPTIONS. -- That is preflighted.
OK, OK I understand, but what do i do?
Now that is clear we have two options to move on:
First Option:
Leaving the web-server structure as is i.e:
www.example.com -> Angular Web-App
api.example.com -> API - subdomain
FOR POST:
And add a transformRequest setting to $httpProvider like so:
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
(Remember preflighted, well it does allow us to send x-www-form-urlencoded.)
What is left from there is make sure you set your data in x-www-form-urlencoded format looks like so :
name=Andy&nickname=RainbowWarrior&....
FOR DELETE:
This one is a bit more complicated since you have to do some server side tweak.
If you are using Slimframework for PHP like I do, all you got to do is:
$response = $app->response();
$response->header('Access-Control-Allow-Origin', '*');
$app->options('/path/to/resource',function(){}); // This one just so you can accept OPTIONS it does nothing.
$app->delete('/path/to/resource',function()
{//your delete code is here
});
Now whenever you try to perform DELETE from angular you will see on XHR tab in w/e browser you are using that There is OPTIONS request that was made and right after DELETE.
Second Option:
Much less of a headache .
Move your API into the same domain i.e
www.example.com - Webapp
www.example.com/api - API
And you are protected from all of that above.
This took me 7 hours of research I hope it will help you guys and save you time!.

jquery fileupload cross domain

I have a small problem i need to create a fileuploader to a remote server using jquery Blueimp Fileupload, if i work locally for testing it is working perfectly now when I tested it on live, Im having a problem with cross origin resource sharing.
Now, how can I retrieve the json response from another domain without using jsonp because I tried jsonp and it does not work with the fileuploader so now I want to do it using json alone and get the response that i need if thats possible
I also tried putting callback=? at the end of url .. also did not work
Or if its possible how can I integrate jsonp with this fileuploader
$( '#fileuploader' ).fileupload( {
sequentialUploads: true,
url: 'http://www.domain.com/test/upload?callback=?',
dropZone: $( '#fileuploader' )
} );
Server Side this is on another domain
echo json_encode( array( 'test' => 'value1') );
Also: i am not allowed to use ftp / curl for this.. thanks
you can allow CORS request at server as:
header("Access-Control-Allow-Origin:*");
header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
When CORS is enabled at server, Ajax first send OPTIONS request to detect whether server allow CORS request or not. if enabled, it send actual request.
If you have allowed the CORS policy on the remote server as suggest above and you still get the Cross Origin error it could be that there is something else not working in your code. Many times Firebug or similar tools show a Cross Origin error and in reality it was a 404 or something else. First question to answer is if you actually at a CORS pre-flight request/response. That's your permission ticket. Check out these posts here here and here
You might consider using the iframe transport option. This will let you keep away from issues with browser that doesn't support cross-domain file uploads, like our old (but still widely used) friend IE 9 or previous versions.
Hope this helps.

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?

How to get json data coming from another domain?

I want to use the google images api. In the past when I worked with json I simply used the ajax function to get the json from my own server. But now I will be getting it from an external domain:
https://ajax.googleapis.com/ajax/services/search/images?q=fuzzy monkey&v=1.0
Obviously I can't load this using js since its not from an internal url. So in these cases how does one work with json data. Are you supposed to load it via CURL using a server side script or is there another way?
You can make use of JSONP by adding a callback GET param.
https://ajax.googleapis.com/ajax/services/search/images?q=fuzzy%20monkey&v=1.0&callback=hello
Then you can request it with jQuery's $.getJSON().
$.getJSON('https://ajax.googleapis.com/ajax/services/search/images?q=fuzzy%20monkey&v=1.0&callback=?', function(response) {
console.log(response.responseData);
});
jsFiddle.
You must use Cross Origin Resource Sharing (CORS http://en.wikipedia.org/wiki/Cross-Origin_Resource_Sharing)
It's not as complicated as it sounds...simply set your request headers appropriately...in Python it would look like:
self.response.headers.add_header('Access-Control-Allow-Origin', '*');
self.response.headers.add_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
self.response.headers.add_header('Access-Control-Allow-Headers', 'X-Requested-With');
self.response.headers.add_header('Access-Control-Max-Age', '86400');

Categories