How to handle (failed) validation when creating multiple entities with a REST API - validation

Let's say I have an endpoint user/1/results and I want to upload multiple results at a time.
So I send it JSON like:
{
"data": [
{
"date": "2014-02-14 03:15:41",
"score": 18649,
"time": 42892
},
{
"date": "2013-11-18 09:21:46",
"score": 7856,
"time": 23568.8
}]
}
Let's say time needs to be an integer, so the second entity fails validation.
What's the best thing to do:
Fail both, nothing saves, respond with error message..
Save first entity, respond with error message.
In either case, what would an error message look like? i.e. how/does it specify that it's the second entity that fails validation.

I think you should fail both and respond with an error message because it might be cumbersome again to track the remaining results.
Error message should give the details of failing location. for example if it fails at the second one then specify it in json response.

Related

Is it possible to accessing GraphQL validation errors from a Relay mutation?

I'm somewhat new to GraphQL, so, still piecing all moving parts together in my head.
On my server side I'm using TypeGraphQL which uses class-validator to perform validation of the queries coming in. On the client side I'm using Relay. When the validations fail, my commitMutation call in Relay calls onError and passes a string representation of the error, but the actual response from the server looks like this:
{
"errors": [
{
"message": "Argument Validation Error",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"updateCurrentUser"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"validationErrors": [
{
"target": {
"name": "ueoa",
"nickname": "ueoa",
"email": ""
},
"value": "",
"property": "email",
"children": [],
"constraints": {
"isEmail": "email must be an email"
}
}
],
"stacktrace": [
"Error: Argument Validation Error",
" at Object.validateArg (C:\\Users\\pupeno\\Documents\\Flexpoint Tech\\imok\\node_modules\\type-graphql\\dist\\resolvers\\validate-arg.js:24:15)",
" at runMicrotasks (<anonymous>)",
" at processTicksAndRejections (internal/process/task_queues.js:97:5)",
" at async Promise.all (index 0)"
]
}
}
}
],
"data": null
}
In this case, I left the email blank and thus on errors[0].extensions.exception.validationErrors[0].constraints.isEmail I have the error: "email must be an email".
Is there a way for Relay to let me access this structure to turn this errors into UI errors for the user? Or are these errors the equivalent of a 500 and I should implement my own separate error handling (equivalent of a 401)?
I do most of my validation on the client, but uniqueness can only be on done on the server and I'm trying to figure out the protocol between the two.
I don't know much about relay but I have used Typegraphql for sometime. What I can tell is that error from class-validator is nested differently from standard error (I am talking about throw new Error('this will be different'). I would advice for you to have an error formatter function on back-end so that regardless of type of error is thrown you can just return a standard graphql error. In apollo server there is option for formating error I believe other graphql servers has one too. Here is how it looks
const apolloServer = new ApolloServer({
formatError: (error) => error,
});
If class-validator's error is thrown error above will be ArgumentValidationError So if error is instance of ArgumentValidationError you need to proper format it and return to the client with all constraints values extracted and appended on message field. In this way all errors will behave the same on front-ent.
It is really hard to handle the error when it comes to graphQL as at the end of the result you will going to get 200 OK responses.
These errors you are getting are the INTERNAL SERVER ERROR, Equivalent to 500.
So, in this case, you'll need to handle it on your own.
As Nux wrote, Apollo has error handling modules, you can refer it from here This might be helpful.
Also As you mention that you are doing most of the validation from the client end, it is not a good idea to do validations only client-side as it can be brack and might become the Major breach.

412 (Precondition Failed) when add attachments at same time

I am using Microsoft Graph. I try to add two attachments by
POST /me/messages/{messageId}/attachment
{
"#odata.type": "#microsoft.graph.fileAttachment",
"name": "1.txt",
"contentBytes": "SGVsbG8gd29ybGQh"
}
POST /me/messages/{messageId}/attachment
{
"#odata.type": "#microsoft.graph.fileAttachment",
"name": "2.txt",
"contentBytes": "SGVsbG8gd29ybGQhIQ=="
}
It gave me 412 (Precondition Failed) error when I add these two attachments at same time.
{
"code": "ErrorIrresolvableConflict",
"message": "The send or update operation could not be performed because the change key passed in the request does not match the current change key for the item., Cannot save changes made to an item to store.SaveStatus: IrresolvableConflict\r\nPropertyConflicts:\r\n",
"innerError": {
"request-id": "20e95141-5d2d-41e3-8eed-3bbd24bcf52a",
"date": "2017-11-28T07:18:45"
}
}
Right now the walkaround way is delaying the second POST around 100 milliseconds. If less than 100 milliseconds, it will be more likely to fail. (The chance to fail might also be related with the size of attachment, I didn't do further test)
But if I have 10 attachments, between each two POSTs, there will be 100 milliseconds delay.
BTW, I saw this issue even exists in Outlook client, when people send mail, they got same error: check here. So it might be a server issue.
[Just move from my original question to answer]

How to check jsonPath for value to expect on different property

I have error messages that comes back in the following structure:
[{
"detail": "must be unique",
"source": {
"pointer": "name"
}
}]
I've omitted unnecessary bits for the sake of this example. In my test, I can do the following:
mockMvc.perform(post(URL)
.contentType(contentType)
.content(this.json(brand)))
.andExpect(status().isUnprocessableEntity())
.andExpect(jsonPath("$.[0].detail", is("must be unique")));
However, if I am testing that I get multiple errors back, $.[0].detail isn't always Name. So I need to first check what the $.[0].source.pointer is and then validate the detail message. I'm just unsure on how to go about doing that.

transfer a sibling element in a reponse to a parameter in Ready API / SOAP UI

I have one REST endpoint which returns a response like this
[
{
"id": "dbfff519-e8f6-4db3-9e26-a4e9014dc360",
"code": "123456789012345678901234567890123456789012345678901234567890",
"name": "client-code-with-character-length-sixty",
},
{
"id": "a673fb54-3503-4996-ba9b-a4e9014dc3ea",
"code": "18MTH",
"name": "18 Month",
},
{
"id": "60b781e3-4515-40f5-81ee-a4e9014dc400",
"code": "2periods",
"name": "I Have 2 Periods",
}...
etc.
I would like to be able to retrieve the ID where, for example, the code="2periods" UI can retrieve using either ResponseAsxml (with xpath) or Response with JSONPath. If I use the former I have managed to get the following to nearly retrieve my ID
//Response[1]/e[code='2periods']/id
BUT this looks like this
<id>0bc4aa5f-f8ab-4efe-b788-a4e9014dc45f</id>
And I don't know how to remove the start and end tags, the id has to be just the GUID.
I can't work out how to do something similar in the JSONPath - I've only managed to get something like
$[3].id
to work, but the order of the entities is not guaranteed in the test environment.
For ResponseAsXml using the XPath to get only the id value without <id> tag just add /text() to your actual expression:
//Response[1]/e[code='2periods']/id/text()
If you want to do the same using Response property with JSONPath try with:
$..[?(#.['code']=='2periods')].id[0]
Hope it helps,

Mailchimp API 2.0 lists/subscribe responding with error 250 List_MergeFieldRequired MMERGE4 is required

I'm attempting to use the lists/subscribe Mailchimp API 2.0 endpoint to subscribe an email to a list, but I keep getting a puzzling error. My request looks like:
{
"apikey":"myapikey-us5",
"id":"listid",
"email":{"email":"my#email.com"},
"double_optin":false,
"send_welcome":true
}
I'm sending this to https://us5.api.mailchimp.com/2.0/lists/subscribe.json and getting this response:
{
"status": "error",
"code": 250,
"name": "List_MergeFieldRequired",
"error": "MMERGE4 must be provided - Please enter a value"
}
And if I specify "merge_vars": {} I still get the same error. What am I missing here?
It means you need to provide a value for MMERGE4 merge field. How you do this depends on what type of merge field MMERGE4 is, but It would be like this:
{
"apikey":"myapikey-us5",
"id":"listid",
"email":{"email":"my#email.com"},
"double_optin":false,
"send_welcome":true,
"merge_vars": {
"MMERGE4": "something"
}
}
But you should look and see what type of data that is, otherwise you might cause issues for whomever set that up as a required field.

Resources