Rails - how to get response properly? - ruby-on-rails

uri = URI(some_url)
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri)
response = http.request(request)
puts response.read_body
Try to on browser, it returns result like this.
[
{
"id": 663,
"name": "string1"
},
{
"id": 644,
"name": "string2"
},
{
"id": 685,
"name": "string3"
},
]
But I am getting this error with my code.
Error: Net::HTTPBadResponse:wrong status line: "\x15\x03\x01\x00\x02\x02"

Related

Query parameters are not percent-encoded for curl with OpenAPI

I generate open api documentation with springdoc 1.6.7 .
When i want to test an endpoint with following query parameter on swagger ui:
{
"page": 0,
"size": 0,
"sort": "string",
"order": "asc",
"q": {
"any": "string",
"firstName": "string",
"lastName": "string",
"email": "string",
"company": "string",
"login": "string",
"noSubscription": true
}
}
It generate following curl request:
curl -X 'GET'
'https://myEndpoint?page=0&size=0&sort=string&order=asc&q[any]=string&q[firstName]=string&q[lastName]=string&q[email]=string&q[company]=string&q[login]=string&q[noSubscription]=true'
-H 'accept: application/json'
The character '[' and ']' are not encoded, so curl request doesn't work.
Here java code from swagger is generated:
#Operation(summary = "XXXX", description = "XXX")
#ApiResponses(value = {
#ApiResponse(responseCode = "200", description = "Success",
content = { #Content(mediaType = "application/json",
schema = #Schema(implementation = PageCollectionContact.class)) }),
#ApiResponse(responseCode = "400", description = "Invalid query parameters",
content = { #Content(
schema = #Schema(implementation = ApiErrorsDTO.class))})})
PageCollectionDTO<AddressBookUserDTO> getContacts(#EffectivePrincipaleUserInfo EffectiveUserInfo userInfo,
#Parameter(description = "Contains parameter to filter response",in = ParameterIn.QUERY) #ModelAttribute AddressBookFilterDTO filterDTO,
HttpServletResponse response,
HttpServletRequest request);

Bad Request "ErrorExecuteSearchStaleData" in Microsoft Graph API - Search for Mails

We are using Microsoft Graph Search API to search through our O365 emails. Since the search only allows 25 results per request for mails. (see https://learn.microsoft.com/en-us/graph/api/resources/search-api-overview?view=graph-rest-beta#page-search-results)
We figured to work around this by batching our search request like this:
POST https://graph.microsoft.com/beta/$batch
{
"requests": [
{
"url": "/search/query",
"method": "POST",
"id": "MyMails-0",
"body":
{
"requests": [
{
"entityTypes": ["message"],
"query":
{
"query_string":
{
"query": "some search text"
}
},
"from": 0,
"size": 25
}
]
},
"headers":
{
"Content-Type": "application/json"
}
},
{
"url": "/search/query",
"method": "POST",
"id": "MyMails-1",
"body":
{
"requests": [
{
"entityTypes": ["message"],
"query":
{
"query_string":
{
"query": "some search text"
}
},
"from": 25,
"size": 25
}
]
},
"headers":
{
"Content-Type": "application/json"
}
},
{
"url": "/search/query",
"method": "POST",
"id": "MyMails-2",
"body":
{
"requests": [
{
"entityTypes": ["message"],
"query":
{
"query_string":
{
"query": "some search text"
}
},
"from": 50,
"size": 25
}
]
},
"headers":
{
"Content-Type": "application/json"
}
},
{
"url": "/search/query",
"method": "POST",
"id": "MyMails-3",
"body":
{
"requests": [
{
"entityTypes": ["message"],
"query":
{
"query_string":
{
"query": "some search text"
}
},
"from": 75,
"size": 25
}
]
},
"headers":
{
"Content-Type": "application/json"
}
}
]
}
This works usually well, but in some cases the API returns something like this:
{
"id": "MyMails-2",
"status": 400,
"headers":
{
"Link": "<https://developer.microsoft-tst.com/en-us/graph/changes?$filterby=beta,RemoveDeprecatedUnderscoreProperty&from=2021-12-01&to=2022-01-01>;rel=\"deprecation\";type=\"text/html\",<https://developer.microsoft-tst.com/en-us/graph/changes?$filterby=beta,RemoveDeprecatedUnderscoreProperty&from=2021-12-01&to=2022-01-01>;rel=\"deprecation\";type=\"text/html\",<https://developer.microsoft-tst.com/en-us/graph/changes?$filterby=beta,RemoveDeprecatedUnderscoreProperty&from=2021-12-01&to=2022-01-01>;rel=\"deprecation\";type=\"text/html\"",
"Deprecation": "Tue, 14 Dec 2021 23:59:59 GMT",
"Sunset": "Sat, 31 Dec 2022 23:59:59 GMT",
"Cache-Control": "no-cache",
"Content-Type": "application/json"
},
"body":
{
"error":
{
"code": "BadRequest",
"message": "\r\n An exception occurred\r\n Lss call failed with status code 400. \"Exchange service returned error ErrorExecuteSearchStaleData: Please reissue the query with rowOffset = 0. The specified rowoffset is '50', but the results are stale.\".",
"innerError":
{
"date": "2022-01-25T09:58:53",
"request-id": "75def95f-a857-427d-a8b4-ee2792329e87",
"client-request-id": "75def95f-a857-427d-a8b4-ee2792329e87"
}
}
}
}
I noticed the deprecation note in the header, however I can't find anything about it. Neither about the actual exception.
What am I missing?
[workaround]
Thanks for the hint #user2250152.
This heavily reduced the issue by splitting the request into two requests, while the second is able to request more than 25 mails at a time:
POST https://graph.microsoft.com/beta/$batch
{
"requests": [
{
"url": "/search/query",
"method": "POST",
"id": "MyMails-0",
"body": {
"requests": [
{
"entityTypes": [
"message"
],
"query": {
"query_string": {
"query": "some search text"
}
},
"from": 0,
"size": 25
}
]
},
"headers": {
"Content-Type": "application/json"
}
},
{
"url": "/search/query",
"method": "POST",
"id": "MyMails-1",
"body": {
"requests": [
{
"entityTypes": [
"message"
],
"query": {
"query_string": {
"query": "some search text"
}
},
"from": 25,
"size": 200
}
]
},
"headers": {
"Content-Type": "application/json"
}
}
]
}
The error with stale results can happen time to time.
You can decrease the number of batch requests to reduce a chance that the error with stale results will occur.
For the first page "from": 0 the max size is 25. But for the next page "from": 25 you can increase the page size to 200.
I've tested the search query with "from": 25 and "size": 200 and it returns 200 results.
Resources:
Page search results

Mountebank - How do I assert message body is JSON format in a POST request in mountebank

I want to stub and check the message body in POST request in mountebank,
{
"port": "22001",
"protocol": "http",
"name": "login_user",
"stubs": [
{
"responses": [
{
"is": {
"statusCode": 201,
"headers": {
"Content-Type": "application/json"
},
"body": {}
},
"_behaviors": {
"wait": 100
}
}
],
"predicates": [
{
"equals": {
"path": "/login_user",
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
"body": {
"name": "Tony",
"age": "20"
}
}
}
]
}
]
}
if a message body in JSON format. expected response status Code 200.
for Example
{
"body": {
"name": "Tony",
"age": "20"
}
}
if a message body in JSON format but JSON string. expected response status Code 400.
for Example
{
"body": "{\"name\": \"Tony\", \"age\": \"20\"}"
}
You could achieve this with a 'matches' predicate containing a (pretty crude in this example) regex to capture any string input and return a 400:
"stubs": [
{
"responses": [
{
"is": {
"statusCode": 400,
"headers": {
"Content-Type": "application/json"
},
"body": {}
},
"_behaviors": {
"wait": 100
}
}
],
"predicates": [
{
"matches": {
"path": "/login_user",
"method": "POST",
"body": ".*\\\\\\\"name.*"
}
}
]
},
{
"responses": [
{
"is": {
"statusCode": 201,
"headers": {
"Content-Type": "application/json"
},
"body": {}
},
"_behaviors": {
"wait": 100
}
}
],
"predicates": [
{
"equals": {
"path": "/login_user",
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
"body": {
"name": "Tony",
"age": "20"
}
}
}
]
}
]
Alternatively, you can also specify a default response code of 400 in the imposter declaration, so that anything that doesn't match a specific predicate will return a 400 response by default:
{
"port": "22001",
"protocol": "http",
"name": "login_user",
"defaultResponse": {
"statusCode": 400
},
"stubs": [
{
.... snip ....

Reply sent email by Gmail API

Currently I'm trying to create send and reply using gmail api, in documentation here
Refernces and In-Reply-To must be set in compliance with the RFC 2822 standard, the problem is when I try to get References and In-Reply-To from specified id like below:
`{
"id": "16183e0822247c79",
"threadId": "16183e0822247c79",
"labelIds": [
"SENT"
],
"snippet": "terkait",
"historyId": "1640387",
"internalDate": "1518335984000",
"payload": {
"partId": "",
"mimeType": "multipart/mixed",
"filename": "",
"headers": [
{
"name": "Received",
"value": "from 1059028371380 named unknown by gmailapi.google.com with HTTPREST; Sat, 10 Feb 2018 23:59:44 -0800"
},
{
"name": "Date",
"value": "Sat, 10 Feb 2018 23:59:44 -0800"
},
{
"name": "From",
"value": "jaisanas2#gmail.com"
},
{
"name": "To",
"value": "jaisanas3#gmail.com"
},
{
"name": "Message-Id",
"value": "\u003cCA+8aSZeXMOETdH8NYtd18UWk5eiQnvT0oEnEWy_1HL6mJPuKjw#mail.gmail.com\u003e"
},
{
"name": "Subject",
"value": "terkait"
},
{
"name": "Mime-Version",
"value": "1.0"
},
{
"name": "Content-Type",
"value": "multipart/mixed; boundary=\"--==_mimepart_5a7ff7f050e3_3263ffa0ceb1cc020ea\"; charset=UTF-8"
},
{
"name": "Content-Transfer-Encoding",
"value": "7bit"
}
],
"body": {
"size": 0
},
"parts": [
{
"partId": "0",
"mimeType": "multipart/alternative",
"filename": "",
"headers": [
{
"name": "Content-Type",
"value": "multipart/alternative; boundary=\"--==_mimepart_5a7ff7f05063_3263ffa0ceb1cc01916\"; charset=UTF-8"
},
{
"name": "Content-Transfer-Encoding",
"value": "7bit"
}
],
"body": {
"size": 0
},
"parts": [
{
"partId": "0.0",
"mimeType": "text/html",
"filename": "",
"headers": [
{
"name": "Content-Type",
"value": "text/html; charset=UTF-8"
},
{
"name": "Content-Transfer-Encoding",
"value": "7bit"
}
],
"body": {
"size": 14,
"data": "PHA-dGVya2FpdDwvcD4="
}
}
]
}
]
},
"sizeEstimate": 929
}`
When you see the result there are no headers In-Reply-To and Refernces, my questions is it is possible to reply email using API ?
Here is my code in ruby:
client = google_client user_id
token = Token.find_by_user_id(user_id)
access_token = token.access_token
gmail = Google::Apis::GmailV1::GmailService.new
gmail.authorization = client
message = Mail.new
message.date = Time.now
message.subject = "Re: #{subject}"
message.from = token.email
message.to = "#{to}"
# message.thread_id = "#{thread_id}"
message.message_id = "\u003cCA+8aSZeXMOETdH8NYtd18UWk5eiQnvT0oEnEWy_1HL6mJPuKjw#mail.gmail.com\u003e"
message.part content_type: 'multipart/alternative' do |part|
part.html_part = Mail::Part.new(body: "#{body}", content_type: 'text/html; charset=UTF-8')
end
msg = message.encoded
message_object = Google::Apis::GmailV1::Message.new(raw:message.to_s, thread_id: thread_id, content_type: 'message/rfc822')
gmail.send_user_message('me', message_object)
This code successfully send email in the same thread, but not reply email, here is what looks like inside my gmail sent emails:
As you can see, message with body lauv does not reply message terkait instead I just sent email lauv, my question is how to reply email?
Here you need to set In-Reply-To and References headers. If there is only one email in the thread use the message_id as In-Reply-To and References

QuickBooks API POST using Google Apps Script

Does anyone have a working example of doing a POST to the QuickBooks API using Google Apps Script?
I'm trying to create an estimate using the QuickBooks API, however although the request body below works in the API explorer, from within Apps Script I get:
Error: Fetch failed, code: 400, message: {"Fault":{"Error":[{"Message":"Request has invalid or unsupported property","Detail":"Property Name:Unrecognized token 'Line': was expecting ('true', 'false' or 'null')\n specified is unsupported or invalid","code":"2010"}],"type":"ValidationFault"},"time":"2016-08-02T09:51:28.917-07:00"} (line 195, file "Tests")
But I can't see why the API expects a boolean rather than the "Line" key.
This is how I define it as a POST payload in the code:
var payload = {
"Line": [
{
"Id": "3",
"LineNum": 1,
"Amount": 10,
"DetailType": "SalesItemLineDetail",
"SalesItemLineDetail": {
"ItemRef": {
"value": "2",
"name": "Hours"
},
"UnitPrice": 10,
"Qty": 2
}
},
{
"Amount": 10,
"DetailType": "SubTotalLineDetail",
"SubTotalLineDetail": {}
}
],
"TxnTaxDetail": {
"TotalTax": 0
},
"CustomerRef": {
"value": "1",
"name": "Mr Blobby"
},
"CustomerMemo": {
"value": "Thank you for your business and have a great day!"
},
"TotalAmt": 31.5,
"ApplyTaxAfterDiscount": false,
"PrintStatus": "NeedToPrint",
"EmailStatus": "NotSet",
}
var companyId = PropertiesService
.getUserProperties()
.getProperty('QuickBooks.companyId')
var url = 'https://quickbooks.api.intuit.com/v3/company/' + companyId + '/estimate'
var options = {
headers: {
'Accept': 'application/json'
},
contentType: 'application/json',
method: 'post',
payload: payload,
muteHttpExceptions: true,
}
var service = OAuth1_.getService();
var response = service.fetch(url, options)
You need to stringify the whole payload before passing it to the OAuth.fetch() call.
So
var payload = JSON.stringify({
"Line": [
{
"Id": "3",
.
.
})

Resources