415 Unsupported Media Type in post request - vue.js

Does anyone know what could cause ERROR 415 (Unsupported Media Type)? Thank you
createArticleOld : async ({ commit, dispatch }, data) => {
let added = await dispatch('authorizedPostOld',
{ action: 'article',
data,
headers: {
'Content-Type': 'application/json-patch+json',
'Accept': 'application/json-patch+json',
},
}
)
console.log(added)
commit('ADD_ARTICLE', added)
},

Typically, an HTTP response status of 415 is telling you that the format of the data you're sending isn't accepted by the server, as described briefly here:
The origin server is refusing to service the request because the payload is in a format not supported by this method on the target resource.
The format problem might be due to the request's indicated Content-Type or Content-Encoding, or as a result of inspecting the data directly.
So, to solve the problem, you need to find out the format that the server expects to receive data in, and send that. The easiest way will be to check the documentation for (or ask the developer of) the server.
If you check the raw response returned to your browser (or perform the same request via something like cURL or Postman), you might find some clues in there as to the formats that the endpoint accepts, or the specific problem causing the error response.
Of course, this relies on the developer of the server implementing the HTTP statuses correctly, and it's quite possible that they've made an error. As a complete guess, given that you're setting the Accept header, it could be that the server is trying to tell you that it can't give you a response in the format "application/json-patch+json", although that should give you a 406.

Related

How to distinguish between GET and POST

I'm writing a simple api for training using express. Here's my testing code:
var express = require('express');
var app = express();
app.post("/api/:var_name", function(req, res) {
res.send(req.params.var_name);
});
is simply testing to see if POST is working. When I call http://localhost:3000/api/1 I get Cannot GET /api/1, so the server is obviously interpreting the POST request as GET, what do I need to do to call POST instead?
Anything you call in the address bar of your browser will be sent via get. This is due to the fact that post-messages (and almost all other methods) do have a body-part. But there is no way for your browser to send additional information inside the body of the http packet.
If you want to test your routes for any method other than GET I would suggest you download a tool like postman.
https://www.getpostman.com/
BEWARE: This is my preference. You can of curse also use text based browsers like curl to test it.
The server interprets the request according to the verb you set in the HTTP request. If no method/verb is specified it is interpreted as GET(not sure about this part).
When you call that URL, you need to use the method as well. For example if you use the fetch API, you can call it like:
fetch(url, {method:"POST"})
If you're entering it in your browser and expect it to be interpreted as a post request, it's not. All browser url requests are GET. Use a tool like Postman to call different HTTP verbs. It's really useful when creating such APIs.
You can check out this answer on details of how to add body and headers to a post request: Fetch: POST json data

Restangular: How to get HTTP response header?

I have a REST server which returns a Link HTTP header with a response to a PUT to indicate the URL of the newly-created entity:
Link:<entities/6>; rel="created"
Is there any possibility to read that link header with Restangular?
The only facility to intercept HTTP requests with Restangular I've met so far is to register a response interceptor in the app config:
restangular.addResponseInterceptor(function (data, operation, what, url, response, deferred) {
console.log(response.headers())
return response.data;
});
However, with above demo implementation in place, the only HTTP header which gets logged is content-type. Still, I can see in the browser development toolbar that a response comes indeed with many additional HTTP response headers, such as Server, Date, and the aforementioned Link.
Why do I not have access to the full array of HTTP response headers through addResponseInterceptor()? Is there any way to capture the HTTP response header in question using Restangular?
Note: I don't search for an answer using HAL or any other special response body format. I would rather like to know whether I can use plain HTTP headers with Restangular or not (if not, I will probably resort to HAL or something).
You don't need a ResponseInterceptor to do this. You just need to set fullResponse to true to get the whole response (including the http headers) every time you do any request.
Restangular.setFullResponse(true);
You can set it globally in your app configuration. Something like this:
angular.module('YourApp')
.config(['RestangularProvider',
function (RestangularProvider) {
RestangularProvider.setFullResponse(true);
...
Then, every time you receive a response, you can access all the response headers.
Restangular.all('users').getList().then(function(response) {
$scope.users = response.data;
console.log(response.headers);
}
Example:
response.headers('Link')
NOTE: Be careful because using fullResponse, the response data is located in response.data, not directly in response.
EDIT: As #STEVER points, you also need to expose the headers in your server API.
Example:
Access-Control-Expose-Headers: Link
You can get more detailed information in Restangular documentation
Hope it helps.

REST API design of a resource whose properties are not editable by the client

What's the best way to handle resource properties which must be modified/updated through another method that is not exposed to the API consumer?
Examples:
Requesting a new token to used for X. The token must be generated following a specific set of business rules/logic.
Requesting/refreshing the exchange rate of a currency after the old rate expires. The rate is for informational purposes and will be used in subsequent transactions.
Note that in the above two examples, the values are properties of a resource and not separate resources on their owns.
What's the best way to handle these types of scenarios and other scenarios where the API consumer doesn't have control of the value of the property, but needs to request a new one. One option would be to allow a PATCH with that specific property in the request body but not actually update the property to the value specified, instead, run the necessary logic to update the property and return the updated resource.
Lets look at #1 in more detail:
Request:
GET /User/1
Response:
{
"Id": 1,
"Email": "myemail#gmail.com",
"SpecialToken": "12345689"
}
As the consumer of the API, I want to be able to request a new SpecialToken, but the business rules to generate the token are not visible to me.
How do I tell the API that I need a new/refreshed SpecialToken with in the REST paradigm?
One thought would be to do:
Request:
PATCH /User/1
{
"SpecialToken": null
}
The server would see this request and know that it needs to refresh the token. The backend will update the SpecialToken with a specific algorithm and return the updated resource:
Response:
{
"Id": 1,
"Email": "myemail#gmail.com",
"SpecialToken": "99999999"
}
This example can be extended to example #2 where SpecialToken is an exchange rate on resource CurrencyTrade. ExchangeRate is a read only value that the consumer of the API can't change directly, but can request for it to be changed/refreshed:
Request:
GET /CurrencyTrade/1
Response:
{
"Id": 1,
"PropertyOne": "Value1",
"PropertyTwo": "Value2",
"ExchangeRate": 1.2
}
Someone consuming the API would need a way to request a new ExchangeRate, but they don't have control of what the value will be, it's strictly a read only property.
You're really dealing with two different representations of the resource: one for what the client can send via POST / PUT, and one for what the server can return. You are not dealing with the resource itself.
What are the requirements for being able to update a token? What is the token for? Can a token be calculated from the other values in User? This may just be an example, but context will drive how you end up building the system.
Unless there were a requirement which prohibited it, I would probably implement the token generation scenario by "touching" the resource representation using a PUT. Presumably the client can't update the Id field, so it would not be defined in the client's representation.
Request
PUT /User/1 HTTP/1.1
Content-Type: application/vnd.example.api.client+json
{
"Email": "myemail#gmail.com"
}
Response
200 OK
Content-Type: application/vnd.example.api.server+json
{
"Id": 1,
"Email": "myemail#gmail.com",
"SpecialToken": "99999999"
}
From the client's perspective, Email is the only field which is mutable, so this represents the complete representation of the resource when the client sends a message to the server. Since the server's response contains additional, immutable information, it's really sending a different representation of the same resource. (What's confusing is that, in the real world, you don't usually see the media type spelled out so clearly... it's often wrapped in something vague like application/json).
For your exchange rate example, I don't understand why the client would have to tell the server that the exchange rate was stale. If the client knew more about the freshness of the exchange rate than the server did, and the server is serving up the value, it's not a very good service. :) But again, in a scenario like this, I'd "touch" the resource like I did with the User scenario.
There are many approaches to that. I'd say the best one is probably to have a /User/1/SpecialToken resource, that gives a 202 Accepted with a message explaining that the resource can't be deleted completely and will be refreshed whenever someone tries to. Then you can do that with a DELETE, with a PUT that replaces it with a null value, and even with a PATCH directly to SpecialToken or to the attribute of User. Despite what someone else mentioned, there's nothing wrong with keeping the SpecialToken value in the User resource. The client won't have to do two requests.
The approach suggested by #AndyDennie, a POST to a TokenRefresher resource, is also fine, but I'd prefer the other approach because it feels less like a customized behavior. Once it's clear in your documentation that this resource can't be deleted and the server simply refreshes it, the client knows that he can delete or set it to null with any standardized action in order to refresh it.
Keep in mind that in a real RESTful API, the hypermedia representation of user would just have a link labeled "refresh token", with whatever operation is done, and the semantics of the URI wouldn't matter much.
I reckon you should consider making SpecialToken a resource, and allow consumers of the api to POST to it to retrieve a new instance. Somehow, you'll want to link the User resource to a SpecialToken resource. Remember, one of the central tenets of REST is that you should not depend on out-of-band information so if you want to stay true to that you'll want to investigate the possibility of using links.
First, let's look at what you've got:
Request:
GET /User/1
Accept: application/json
Response:
200 OK
Content-Type: application/json
{
"Id": 1,
"Email": "myemail#gmail.com",
"SpecialToken": "12345689"
}
While this response does include the SpecialToken property in the object, because the Content-Type is application/json will not actually mean anything to clients that aren't programmed to understand this particular object structure. A client that just understands JSON will take this as an object like any other. Let's ignore that for now. Let's just say we go with the idea of using a different resource for the SpecialToken field; it might look something like this:
Request:
GET /User/1/SpecialToken
Accept: application/json
Response:
200 OK
Content-Type: application/json
{
"SpecialToken": "12345689"
}
Because we did a GET, making this call ideally shouldn't modify the resource. The POST method however doesn't follow those same semantics. In fact, it may well be that issuing a POST message to this resource could return a different body. So let's consider the following:
Request:
POST /User/1/SpecialToken
Accept: application/json
Response:
200 OK
Content-Type: application/json
{
"SpecialToken": "98654321"
}
Note how the POST message doesn't include a body. This may seem unconventional, but the HTTP spec doesn't prohibit this and in fact the W3C TAG says it's all right:
Note that it is possible to use POST even without supplying data in an HTTP message body. In this case, the resource is URI addressable, but the POST method indicates to clients that the interaction is unsafe or may have side-effects.
Sounds about right to me. Back in the day, I've heard some servers had problems with POST messages without a body, but I personally have not had a problem with this. Just make sure the Content-Length header is set appropriately and you should be golden.
So with that in mind, this seems like a perfectly valid way (according to REST) to do what you're suggesting. However, remember before when I mentioned the bits about JSON not actually having any application level semantics? Well, this means that in order for your client to actually send a POST to get a new SpecialToken in the first place, it needs to know the URL for that resource, or at least how to craft such a URL. This is considered a bad practice, because it ties the client to the server. Let's illustrate.
Given the following request:
POST /User/1/SpecialToken
Accept: application/json
If the server no longer recognizes the URL /User/1/SpecialToken, it might return a 404 or other appropriate error message and your client is now broken. To fix it, you'll need to change the code responsible. This means your client and server can't evolve independently from each other and you've introduced coupling. Fixing this however, can be relatively easy, provided your client HTTP routines allow you to inspect headers. In that case, you can introduce links to your messages. Let's go back to our first resource:
Request:
GET /User/1
Accept: application/json
Response:
200 OK
Content-Type: application/json
Link: </User/1/SpecialToken>; rel=token
{
"Id": 1,
"Email": "myemail#gmail.com",
"SpecialToken": "12345689"
}
Now in the response, there's a link specified in the headers. This little addition means your client no longer has to know how to get to the SpecialToken resource, it can just follow the link. While this doesn't take care of all coupling issues (for instance, token is not a registered link relation,) it does go a long way. Your server can now change the SpecialToken URL at will, and your client will work without having to change.
This is a small example of HATEOAS, short for Hypermedia As The Engine Of Application State, which essentially means that your application discovers how to do things rather than know them up front. Someone in the acronym department did get fired for this. To wet your appetite on this topic, there's a really cool talk by Jon Moore that shows an API that makes extensive use of hypermedia. Another nice intro to hypermedia is the writings of Steve Klabnik. This should get you started.
Hope this helps!
Another thought just occurred to me. Rather than model a RefreshToken resource, you could simply POST the existing special token to a RevokedTokens collection that's associated with this User (assuming that only one special token is allowed per user at a given time).
Request:
GET /User/1
Accept: application/hal+json
Response:
200 OK
Content-Type: application/hal+json
{
_links: {
self: { href: "/User/1" },
"token-revocation": { href: "/User/1/RevokedTokens" }
},
"Id": 1,
"Email": "myemail#gmail.com",
"SpecialToken": "12345689"
}
Following the token-revocation relation and POSTing the existing special token would then look like this:
Request:
POST /User/1/RevokedTokens
Content-Type: text/plain
123456789
Response:
202 Accepted (or 204 No Content)
A subsequent GET for the user would then have the new special token assigned to it:
Request:
GET /User/1
Accept: application/hal+json
Response:
200 OK
Content-Type: application/hal+json
{
_links: {
self: { href: "/User/1" },
"token-revocation": { href: "/User/1/RevokedTokens" }
},
"Id": 1,
"Email": "myemail#gmail.com",
"SpecialToken": "99999999"
}
This has the advantage of modeling an actual resource (a token revocation list) which can effect other resources, rather than modeling a service as a resource (i.e., a token refresher resource).
How about a separate resource which is responsible for refreshing the token within the User resource?
POST /UserTokenRefresher
{
"User":"/User/1"
}
This could return the refreshed User representation (with the new token) in the response.

Why can't I make a GET request to flickr api but I the request works when all the parameters are embedded in the string?

I'm trying to make a request to the Flickr api using two methods:
Directly going to
http://www.flickr.com/services/rest/?method=flickr.photos.search&api_key=KEYHERE&text=lol
Going to http://www.requestmaker.com and setting the URL to http://www.flickr.com/services/rest/ and setting appropriate values for headers api_key, text and method.
The second method never works, but the first method does. I'm ensuring the request is a GET request. Any idea why?
I also tried other similar sites for #2 and I'm getting the same error.
I've never used requestmaker until now, but I just tried and it works for me. I'm guessing your input is incorrect - try one of these two methods:
are you using requestmaker GET or POST method (it's the top-right dropdown)?
if GET, then
Request URL: http://www.flickr.com/services/rest/? method=flickr.photos.search&api_key=KEYHERE&text=lol
Request Header: Leave as is
Request Data: N/A (you're using GET so nothing to post)
if POST, then
Request URL: http://www.flickr.com/services/rest/
Request Header: N/A (remove the headers)
Request Data: method=flickr.photos.search&api_key=KEYHERE&text=lol

How to access error response body with AngularJS

my head is spinning cause of the following issue. I'm accessing my webservice (running on my localhost:4434) with AngularJS and if something goes wrong, the webservice sends a response 400 containing a json body which contains a message that tells you what exactly went wrong.
Problem is I cannot access the message on the client? It is almost as if it never reaches the client?? (This isn't the case, I've confirmed that it reaches the client already) This is the angular code that I use on the client site.
$scope.create = function() {
$http.post('http://localhost:4434/scrapetastic/foo', $scope.bar).
success(function(data, status, headers, config) {
console.log("Call to log: "+status);
console.log("Call to log: "+data);
}).
error(function(data, status) {
console.log("Error|Data:"+data);
console.log(status);
});
}
If I submit malformed data a corresponding error response is generated but as I said ... somehow I cannot access the message that is contained in the response body. This is what I get:
I've tried all sorts of things but am seriously stuck now...perhaps someone has an idea on how to access the payload of the response or at least what to do next? I'm also dealing with CORS perhaps it has something to do with that.
Thanks!
I'm going to take a wild guess here and say that your problem is an XSS issue.
Not only do you not have the data variable, but as far as I can tell from your screenshot, status == 0.
Your screenshot also says Origin: http://localhost, which makes this request considered XSS (since the port is different). That would explain why status is 0.
Edit: You can use jsonp to get around the issue.