JSON POST request sends only id - reactjs

Hello Everyone I couldn't find any solution so here is my question
I tried to write POST Request and tried to POST data as JSON, it works
but I only get new Object in JSON file with new ID, nothing else is being sent.
This is ReaactJS app to be exact
var url = 'http://localhost:3000/applications'; //Configurable endpoint
var request = new XMLHttpRequest();
var isSent = false;
var data = {
name : this.state.name,
age : this.state.age,
prefix : this.state.prefix,
email : this.state.email
}
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.onload = function () {
isSent = true;
console.log(this.responseText);
};
xhr.send(data);
This is my way to do so

You should check out new fetch API.
The Fetch API provides an interface for fetching resources (including across the network). It will seem familiar to anyone who has used XMLHttpRequest, but the new API provides a more powerful and flexible feature set.
Please check Fetch: POST json data

The problem night be with the formatting of the .rest file
For example
POST http://localhost:3001/api/persons
Content-Type: application/json
{
"name" : "fbgjdbh",
"number" : 89475947
}
this worked for me. You need to leave an empty line after the content-type, then specify the object.
The following was not working for me and was only sending the id.
POST http://localhost:3001/api/persons
Content-Type: application/json
{
"name" : "fbgjdbh",
"number" : 89475947
}

Related

How can I make an authenticated http request and return a stream of objects with dart?

I have to put the API Key in the request header as:
Authorization: Bearer "YOUR API KEY"
This is my code (I'm not sure where to put the header and how)
Future<Stream<Book>> getBooks() async {
var url = ‘example_url’
var client = http.Client();
var streamedResponse = await client.send(
http.Request(‘get’, Uri.parse(url))
);
return streamedResponse.stream
.transform(utf.decoder)
.transform(json.decoder)
.expand(jsonBody) => (jsonBody as Map)[‘results’] )
.map((jsonBook) = Book.fromJson(jsonBook));
}
The Flutter docs https://flutter.io/cookbook/networking/authenticated-requests/ says to use this format for authenticated requests but this is not for streams, this returns a future of an object (Book)
Future<Book> fetchPost() async {
final response = await http.get(
'https://jsonplaceholder.typicode.com/posts/1',
headers: {HttpHeaders.authorizationHeader: "Place your_api_token_here"},
);
final responseJson = json.decode(response.body);
return Book.fromJson(responseJson);
}
You can add custom headers after you created the Request
final request = http.Request('GET'), url)
..headers.addAll(myHeaders);
I have made a custom header using http.Request as follow bellow :
final url =
'https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-10.6.0-amd64-xfce-CD-1.iso';
final request = Request('GET', Uri.parse(url));
request.headers.clear();
request.headers.addAll({"content-type":"application/json"});

Make GET call to REST service with parameters in Angular 2

I am trying to make a GET call to the YouTube Web API but I cannot figure out how to pass parameters using the http.get function. I have used fiddler and made sure the request is being made. I am currently getting a 400 error saying that I am missing a the parameter "Part". How can I modify my code to include the required parameters in my request?
private _url = 'https://www.googleapis.com/youtube/v3/';
private _key = '';
getPlaylistVideos(playlistId, pageToken){
var url = this._url + "playlistItems";
var options = { part: 'snippet', maxResults: 50, playlistId: playlistId, key: this._key, pageToken: pageToken }
return this.http.get(url, options);
}
You need to include the search params in to your request. I think this will work for you:
getPlaylistVideos(playlistId, pageToken) {
let url = `${this._url}playlistItems`,
options = { part: 'snippet', maxResults: 50, playlistId: playlistId, key: this._key, pageToken: pageToken },
params = URLSearchParams();
for (let key in options) params.set(key, options[key);
return this.http.get(url, {search: options});
}
You create the URLSearchParams using the set method you can find the full documentation here
Please have a look at the already asked & solved question regarding AngularJS & YouTube V3 API. See here thanks to #Sandeep Sukhija.
Anyhow, about the missing parameter part, add it to the request ex: part: 'snippet'
Example code :
function getPlaylistVideos(playlistId, pageToken) {
// pass the page token as a parameter to the API
$.get('https://www.googleapis.com/youtube/v3/playlistItems', { part: 'snippet', maxResults: 50, playlistId: playlistId, key: key, pageToken: pageToken })
}
How to use the part parameter
The part parameter is a required parameter for any API request that
retrieves or returns a resource. The parameter identifies one or more
top-level (non-nested) resource properties that should be included in
an API response. For example, a video resource has the following
parts:
snippet contentDetails fileDetails player processingDetails
recordingDetails statistics status suggestions topicDetails

Error 500 and CORS : what's the difference between $http and $window.XMLHttpRequest

In one of my angularJS project, i decided to use ng-droplet, which allow me to create drag-n-drop zone to upload images on server via my api.
After setting the plugin, I tried it, but i get :
XMLHttpRequest cannot load http://myapi.com/api/items. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8383' is therefore not allowed access. The response had HTTP status code 500.
Access-Control-Allow-Origin is set to " * " on server side, and i have no problem to do requests on my other api endpoints.
So I tried to see how the plugin create the request and send it, here's how :
$scope.uploadFiles = function uploadFiles() {
// Reset...
$scope.isError = false;
var httpRequest = new $window.XMLHttpRequest(),
formData = new $window.FormData(),
queuedFiles = $scope.filterFiles($scope.FILE_TYPES.VALID),
fileProperty = $scope.options.useArray ? 'file[]' : 'file',
requestLength = $scope.getRequestLength(queuedFiles),
deferred = $q.defer();
// Initiate the HTTP request.
httpRequest.open('post', $scope.options.requestUrl, true);
/**
* #method appendCustomData
* #return {void}
*/
(function appendCustomData() {
if (!$scope.options.disableXFileSize) {
// Setup the file size of the request.
httpRequest.setRequestHeader('X-File-Size', requestLength);
}
// ...And any other additional HTTP request headers, and POST data.
$scope.addRequestHeaders(httpRequest);
$scope.addPostData(formData);
})();
/**
* #method attachEventListeners
* #return {void}
*/
(function attachEventListeners() {
// Define the files property so that each listener has the same interface.
$scope.listeners.files = queuedFiles;
$scope.listeners.deferred = deferred;
$scope.listeners.httpRequest = httpRequest;
// Configure the event listeners for the impending request.
$scope.listeners.progress();
$scope.listeners.success();
$scope.listeners.error();
})();
// Iterate all of the valid files to append them to the previously created
// `formData` object.
$angular.forEach(queuedFiles, function forEach(model) {
formData.append(fileProperty, model.file);
});
// Voila...
$scope.isUploading = true;
httpRequest.send(formData);
return deferred.promise;
};
As you can see, he's not using $http but $window.XMLHttpRequest.
So I tried to do a file upload in a test controller, on the same end point ( http://myapi.com/api/items ), but this time with $http.
Like so :
var fileInput = document.getElementById('uploadedFile');
var file = fileInput.files[0];
var formData = new FormData();
formData.append('title', "rfsdfsd");
formData.append('description', "rfsdfhgfhfgsd");
formData.append('category', 1);
formData.append('price', 20);
formData.append('file', file);
$http.post('http://myapi.com/api/items', formData, {
headers: {
'Content-Type': undefined
}
});
Note the 'Content-Type': undefined, because when i tried this one, it worked ! Files are actually uploaded and i get a 200 response code.
If i change the Content-Type from undefined to "multipart/form-data", or anything else, or if i remove that line, i got the error from above and upload fail.
In the angular documentation, it is said that setting Content-Type to "undefined" explicitly remove the header :
To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis, Use the headers property, setting the desired header to undefined.
It seems that the fact of removing the Content-Type header is part of the reason that it works with $http.
So I also tried with a $window.XMLHttpRequest inside this test controller :
var httpRequest = new $window.XMLHttpRequest();
var fileInput = document.getElementById('uploadedFile');
var file = fileInput.files[0];
var formData = new FormData();
formData.append('title', "rfsdfsd");
formData.append('description', "rfsdfhgfhfgsd");
formData.append('category', 1);
formData.append('price', 20);
formData.append('file', file);
httpRequest.open('post', 'http://myapi.com/api/items', true);
httpRequest.send(formData);
But this one give me the same CORS error as before. I also tried to manually add a Content-Type header like this :
httpRequest.setRequestHeader('Content-Type', undefined);
or
httpRequest.setRequestHeader('Content-Type', null);
or "", " " etc but nothing seemed to work, i always got :
POST http://myapi.com/api/items 400 (Bad Content-Type header value: 'undefined')
So, why does it work with $http and Content-Type set to undefined and how can i modify ng-droplet to make it work ? ( i don't want to rewrite the whole thing using $http instead of $window.XMTHttpRequest).
Why do i get this error when using $window.XMTHttpRequest or $http without Content-Type header or with Content-Type set to anything but undefined ?
Ps : If anyone ask : ng-droplet provides its own way to add POST data, which are needed on the endpoint that i use. Like so :
$scope.interface.setPostData({title: "test", description: 'testetstsetest', price: 20, category: 1});
So it's not the problem source.
EDIT :
I solved it, I forgot that I had an Http Interceptor which automatically add a Authorization header to all the $http requests. The thing that I didn't know was that it wasnt added to $window.XMLHTTPRequest. So I added it manually and now it works.

DART & GAE : Why a POST method send from dart can't be evaluate in GAE?

I have a Dart code used to send an HttpRequest with a POST method to my GAE WepApp2 application. The dart code is executed in chromium and serve by Chrome dev editor. I add in my GAE code some headers to avoid the XHR error in the client side.
The dart code send the datas to my GAE app but I can't read the data with self.request.POST.get("language")) and the app never enter in def post(self): section but with self.request.body I can read the data.
Could you explain that and provide some correction to have a full POST compliant code?
dart:
void _saveData() {
HttpRequest request = new HttpRequest(); // create a new XHR
// add an event handler that is called when the request finishes
request.onReadyStateChange.listen((_) {
if (request.readyState == HttpRequest.DONE &&
(request.status == 200 || request.status == 0)) {
// data saved OK.
print(request.responseText);
}
});
// POST the data to the server
var url = "http://127.0.0.1:8080/savedata";
request.open("POST", url, async: false);
String jsonData = JSON.encode({"language":"dart"});
request.send(jsonData);
}
GAE code in my handler:
def savedata(self):
logging.info("test")
logging.info(self.request.body)
logging.info(self.request.POST.get("language"))
def post(self):
logging.info("test 2")
logging.info(self.request.POST.get("language"))
self.response.headers["Access-Control-Allow-Origin"] = "http://127.0.0.1:49981"
self.response.headers["Access-Control-Allow-Methods"] = "POST, GET, OPTIONS"
In Dart, if you don't specify request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") in your HttpRequest, the data is considered by GAE like a bite stream and you can only read them with self.request.body
If you add the Content-Type header in Dart you need also to change the data formating. In my case I mimic a form sending with POST method so I change String jsonData = JSON.encode({"language":"dart"}); by String jsonData = "language=dart2";
IN GAE python I can now read the data with self.request.POST.get("language")
If you need to send a JSON from DART to GAE, you can encode the string like this:
String jsonData = JSON.encode({"test":"valuetest1"});
String datas = "datas=$jsonData";
request.send(datas);
In GAE you can read the datas like this:
my_json = json.loads(self.request.POST.get("datas"))
logging.info(my_json["test"])
The complete code:
Dart
void _saveData2() {
String url = "http://127.0.0.1:8080/savedata";
HttpRequest request = new HttpRequest()
..open("POST", url, async: true)
..setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
..responseType = "arraybuffer";
String jsonData = JSON.encode({"test":"valuetest1"});
String datas = "datas=$jsonData";
request.send(datas);
}
GAE
class PageHandler(webapp2.RequestHandler):
def savedata(self):
self.response.headers.add_header('Access-Control-Allow-Origin', '*')
self.response.headers['Content-Type'] = 'application/json'
#logging.info(self.request)
my_json = json.loads(self.request.POST.get("datas"))
logging.info(my_json["test"])

415 (Unsupported Media Type) in $http.post method

I'm quite new to REST and AngularJS, but after several hours of googling I couldn't find any answer to my question:
I'm trying to do a POST request from my angularjs frontend to my backend implemented in java (using JPA).
When I'm trying to create a json-object and to do a POST I always get the 415 (Unsupported Media Type) error.
(Actually I don't even get "into" the scope of the service (i.E. "IN SERVICE" doesn't get printed to the console)..
If I add postData.toJSON(), it actually gets "POSTed", but arrives null ...
how do I have to format my 'postData' in Order to succesfully get POSTed?
(I also tried to write the Date-properties without ' " ' - no luck...)
Thank you for your help!
FrontEnd:
app.controller('WorkController', function($scope, $http) {
$scope.saveWork = function () {
var postData = {
"status" : "OPEN",
"startDate": "1338364250000",
"endDate": "1336364253400",
"WorkText" : "Test"
};
$http.post("http://localhost:8080/service/v1/saveWork", postData)
.success(function(data, status, headers, config){
console.log("IN SAVE WORK - SUCCESS");
console.log(status);
})
.error(function(){
console.log("ERROR IN SAVE WORK!");
})
}
});
Service:
#POST
#Consumes(MediaType.APPLICATION_JSON)
public Response save(WorkDto wo){
System.out.println("IN SERVICE");
if(ass == null){
System.out.println("Could nor persist work- null");
return Response.noContent().build();
} else{
Work workDao = WorkTransformator.transform(wo);
workDao.persist();
return Response.ok().build();
}
}
Instead of building and sending a parsed JSON object, create a javascript object and send that in your post body. You can reuse your postData object, but try removing the "" surrounding properties names.
Try this:
var postData = {
status : "OPEN",
startDate: "1338364250000",
endDate: "1336364253400",
workText : "Test"
};
UPDATE
Looks like the above doesn't work by itself. I thought that the Content-Type would be infered.
Can you try to do the post request this way :
$http({
method: 'POST',
url: 'http://localhost:8080/service/v1/saveWork',
data: postData,
headers: {
'Content-Type': 'application/json'
}}); // complete with your success and error handlers...
// the purpose is to try to do the post request explicitly
// declaring the Content-Type you want to send.
UPDATE 2
If this didn't work, compose a post request using Fiddler, and check what's the response.
Here's some pointers:
Download Fiddler2 if you dont already have it
Compose a request like in the screenshot below
You can then check on the pane on the left for what was the server response code. Double click that line (Ignore the error code on the screenshot...you should be getting a 415)
After double-clicking the response line, you can check and browse for more details on the right pane:
If you can successfuly post with a «manufactured» JSON object then the problem resides on your Angular code. If not, it's certainly something wrong with your Rest Service configuration.
You can also inspect the details of your POSTS made with the Angular app in Fiddler2. That should give you a good insight of what's going on.
If you're into it, you can then update your question with some screenshots of your Angular app requests. That will certainly help us to help you :)
I finally managed to find the cause of my error!
In my Rest-Service, I directly expected my java-class as parameter. (I thought this would be parsed/deserialized automatically). Quite naive I think... :)
In order to get it working I had to:
-Expect a String as Parameter in my #POST service
-Deserialize it (using GSON)
Here is the (now working) service:
#POST
#Consumes(MediaType.APPLICATION_JSON)
public Response save(String wo){
if(wo == null){
System.out.println("Could nor persist work- null");
return Response.noContent().build();
} else{
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HHmm:ssZ").create();
WorkDto dto = gson.fromJson(wo, WorkDto.class);
Work workDao = WorkTransformator.transform(dto);
workDao.persist();
return Response.ok().build();
}
}
Thanks again António for your help!

Resources