Office 365 REST API to create contacts using CURL gets HTTPCode 400 Bad Request - api

I am testing Office 365 REST API using CURL following this link:
Contacts REST API in Office 365 APIs Preview
I can obtain correctly one contact using curl command in Windows like this:
curl --no-sessionid --insecure --basic --user "user#domain.com:password" -H "Accept: application/json" "https://outlook.office365.com/EWS/OData/Me/Contacts?$orderby=DisplayName+asc&$top=1"
And following documentation on this link if I try to create one contact using CURL with minimum required options for testing:
curl -X POST -d "{\"#odata.type\": \"#Microsoft.Exchange.Services.OData.Model.Contact\",\"GivenName\": \"TestContact\",\"EmailAddress1\": \"test#test.com\",\"BusinessPhone1\": \"123-456-7890\"}" https://outlook.office365.com/ews/odata/Me/Contacts --header "Content-Type:application/json" --insecure --verbose --user "user#domain.com:password"
I receive following error:
* About to connect() to outlook.office365.com port 443 (#0)
* Trying 157.56.250.178...
* connected
* Connected to outlook.office365.com (157.56.250.178) port 443 (#0)
* SSLv3, TLS handshake, Client hello (1):
...
* SSL connection using ECDHE-RSA-AES256-SHA
* Server certificate:
...
* Server auth using Basic with user 'user#domain.com'
> POST /ews/odata/Me/Contacts HTTP/1.1
...
> Content-Length: 157
>
* upload completely sent off: 157 out of 157 bytes
< HTTP/1.1 400 Bad Request
...
< Content-Length: 82
<
{"error":{"code":"ErrorInvalidRequest","message":"Cannot read the request body."}}* Connection #0 to host outlook.office365.com left intact
* Closing connection #0
* SSLv3, TLS alert, Client hello (1):
I have searched the internet and in stackoverflow but similar questions have no answer I'm looking for.
How could I create on contact using CURL?, I have tested it on Linux too but have the same results.

The following request works when I try it from Fiddler. Can you please try this out using CURL?
POST https://outlook.office365.com/ews/odata/Me/Contacts HTTP/1.1
Authorization: Basic <XXXX>
Content-Type: application/json
{
"GivenName" : "John",
"EmailAddresses" : [
{ "Address": "John#contoso.com", "Name" : "John" }
],
"BusinessPhones" : [
"123-456-7890"
]
}
I made a few changes to your request. You don't need to specify the OData.type as we infer that you are adding a Contact because you are sending a POST to Contacts collection. We need to fix our documentation as it lists the entity type as required. We have updated our namespace to Microsoft.OutlookServices and hence the type definitions have changed. To make the API easier to use, we have replaced EmailAddress1, EmailAddress2 etc. with a collection of EmailAddresses. Similarly, we have also changed BusinessPhones, HomePhones etc. to collections as well.
As I just explained in another post, the issues you are seeing are from some changes being rolled out to our preview APIs and our documentation is in the process of being updated. The current set of changes include versioning support, and this won't be an issue going forward.
Please let me know if you have any questions or need more info.
Thanks,
Venkat

Using following CURL command worked perfect:
curl -X POST -d "{\"GivenName\":\"John\",\"EmailAddresses\":[{\"Address\":\"John#contoso.com\",\"Name\":\"John\"}],\"BusinessPhones\":[\"123-456-7890\"]}" https://outlook.office365.com/ews/odata/Me/Contacts --header "Content-Type:application/json" --insecure --verbose --user "user#domain.com:password"
Now we can export contacts (this is not allowed from OWA) and import it using simple utilities like curl.
Thanks for your help Venkat.

Your original post showed the following namespace:
Microsoft.Exchange.Services.OData.Model.Contact
That has been changed to:
Microsoft.Office365.OutlookServices.Contact
Since the namespace was wrong, it couldn't read the request body.

Related

How to query SFTP server with Karate via API?

The app that I am trying to test has an SFTP server that can be queried via API. Swagger shows the following sample cURL request to get domain files information, and I am having a hard time making this call with Karate:
curl -X GET -H 'Accept: application/json' 'https://{host}:{port}/api/{clientId}/'
I do the following where baseUrl is defined as https://sftp.mydomain.com:22 where 22 is the port number that I can successfully use to connect to the SFTP server via Cyberduck:
Feature:
Background:
* url baseUrl
* def moduleBase = '/api/12345/'
Scenario:
* path moduleBase
When method get
Then status 200
The error that I get is this:
ERROR com.intuit.karate - src/test/java/mytest.feature:9
When method get
http call failed after 815 milliseconds for url: https://sftp.mydomain.com:22/api/12345/
What am I doing wrong?
Clearly it may not be HTTP so I don't think Swagger and all is legit.
Maybe you can just delegate to the OS. Refer: https://stackoverflow.com/a/64352676/143475

HTTPS requests to paypal sandbox fail

I can't currently use the PayPal Sandbox to test my shopping-cart integrations. When i access the sandbox in a browser or via curl, all i get is connection errors.
Here's an example curl-session:
curl -v "https://api-3t.sandbox.paypal.com/nvp?user=test"
* Trying 173.0.82.83...
* TCP_NODELAY set
* Connected to api-3t.sandbox.paypal.com (173.0.82.83) port 443 (#0)
* TLS 1.2 connection using TLS_RSA_WITH_AES_256_CBC_SHA256
* Server certificate: api-3t.sandbox.paypal.com
* Server certificate: Symantec Class 3 Secure Server CA - G4
* Server certificate: VeriSign Class 3 Public Primary Certification Authority - G5
> GET /nvp?user=test HTTP/1.1
> Host: api-3t.sandbox.paypal.com
> User-Agent: curl/7.51.0
> Accept: */*
>
* SSLRead() return error -9806
* Curl_http_done: called premature == 1
* Closing connection 0
curl: (56) SSLRead() return error -9806
Any hints if this is a serverside issue or something i can work around?
Thanks!
Looks like the NVP/SOAP integration method of Paypal Express Checkout is deprecated as of January 1, 2017. The live URL (https://api-3t.paypal.com/nvp) seems to work for now, but this might be why the sandbox doesn't work anymore.
I don't exactly understand why, but using POST instead of GET when submitting data to the PayPal Sandbox solves the problem nicely. No more weird SSL-errors.
Found below answer to curl 56 error . Hope that could help work out of the problem.
curl (56) Recv failure
PHP CURL Error - curl: (56) Recv failure: Connection reset by peer

how to send correct curl command to webserver

So I got the data that is being sent to a specific server. Now I want to do the same using curl from my local machine to play around with specific repsonses from the server and learn more about curl as well.
Here is part of my data
POST /auth HTTP/1.1
platform: android
X-Auth-Token: <censored>
Content-Type: application/json; charset=utf-8
Host: api.blabla.com
Accept-Encoding: gzip
And the data that is being sent:
{"blabla_token": "sdsadsad", "blahblah_id": "23213", "locale": "us"}
Now when I try cURL in my dos shell, I try
curl --insecure -X POST https://api.blabla.com/auth --data '{"blabla_token": "sdsadsad", "blahblah_id": "23213", "locale": "us"}'
The response I get from cURL is this:
{"code":401,"error":"blablaTokenRequired"}
Even though I specified the token. So there are two possible scenarios because the token is correct:
It has something to do with the SSL thing? (I use --insecure because I get an SSL error otherwise)
Something about my command is not correct but I can't figure out what.
Can someone kindly help me out? I am trying everything I can without success
I am not sure if I understand your application specific right, but probably one thing you need to take into account:
man curl says:
-d, --data <data>
(HTTP) Sends the specified data in a POST request to the HTTP server, in the same way that a browser does when
a user has filled in an HTML form and presses the submit button. This will cause curl to pass the data to the
server using the content-type application/x-www-form-urlencoded. Compare to -F, --form.
-d, --data is the same as --data-ascii. --data-raw is almost the same but does not have a special interpreta‐
tion of the # character. To post data purely binary, you should instead use the --data-binary option. To URL-
encode the value of a form field you may use --data-urlencode.
As I can't see in your example the necessity of sending data as HTML form input, probably your application expects just a "raw" POST body and then you have to try this:
curl --insecure -X POST https://api.blabla.com/auth --data--binary '{"blabla_token": "sdsadsad", "blahblah_id": "23213", "locale": "us"}'
PS and for sure this is error is not about using --insecure which just asks curl to neglect ssl verification
you forgot the headers and enabling compressed encoding (gzip), however, i believe you can't force curl to only support gzip encoding using the curl command line alone, you will have to use libcurl, this will make the request say "Accept-Encoding: gzip,deflate" on most systems, using --compressed .. if that's not acceptable to you, rewrite it using libcurl (where you can force it to say only "gzip", if you wish, via CURLOPT_ENCODING )
curl -X POST https://api.blabla.com/auth --data '{"blabla_token": "sdsadsad", "blahblah_id": "23213", "locale": "us"}' --header 'platform: android' --header 'X-Auth-Token: <censored>' --header 'Content-Type: application/json; charset=utf-8' --header 'Host: api.blabla.com' --compressed
another gotcha: on some systems, there will be a default useragent header (like debian 6), while on some systems, curl comes without a default useragent (like debian 8).. you might want to use --user-agent '' too

Convert curl command to HTTParty Rails

I'm currently trying to send a get request in HTTParty that logs in and gets some API data. I've successfully done this via curl by doing:
curl -v --user USERNAMEHERE:PassWordHere http://app.ionitnetworks.com/ionit-app/api/rest/v1/devices
This outputs in my console:
➜ HeatWatch git:(kunzig_new_heatwatch) ✗ curl -v --user (userOmitted):(password_omitted) http://app.ionitnetworks.com/ionit-app/api/rest/v1/devices
* Hostname was NOT found in DNS cache
* Trying 23.92.23.58...
* Connected to app.ionitnetworks.com (23.92.23.58) port 80 (#0)
* Server auth using Basic with user 'userOmitted'
> GET /ionit-app/api/rest/v1/devices HTTP/1.1
> Authorization: Basic ZG91Z0dofW301320Y2AsayZlLmNvbTpkb3VnMTIz
> User-Agent: curl/7.35.0
> Host: app.ionitnetworks.com
> Accept: */*
I've tried a bunch of stuff to get this to work in httparty but nothing has worked such as:
#response = HTTParty.post("https://app.ionitnetworks.com/ionit-app/api/rest/v1/devices.json", :headers =>{ "Authorization" =>"Token token=\"AccountsTokenOmitted\"" })
Any tips would be greatly appreciated!
I found that for me -u USERNAME:PASSWORD in curl is for the most part equivalent to basic_auth in HTTParty. I also like setting my options in a separate variable to make it a little easier to read/edit/adjust and then pass that variable to the call.
options = {
basic_auth: { username: USERNAME, password: PASSWORD }
}
HTTParty.post(<URL>, options)

Github API 502 error

I'm trying to add a user to a Github repository via their API, but I always get a 502 Bad Gateway error.
With curl I send a request like this (<...> replaced by a real owner, repo, etc.):
curl -i -H 'Authorization: token xxxxxxxxxx' -XPUT https://api.github.com/repos/<owner>/<repo>/collaborators/<username>
I also tried it with this url:
curl -i -H 'Authorization: token xxxxxxxxxx' -XPUT https://api.github.com/teams/<id>/members/<username>
As token I used a newly created Personal Access Tokens
But both times I get this back
HTTP/1.0 502 Bad Gateway
Cache-Control: no-cache
Connection: close
Content-Type: text/html
<html><body><h1>502 Bad Gateway</h1>
The server returned an invalid or incomplete response.
</body></html>
A GET on each URL works fine but a DELETE doesn't work either. So maybe it has to do with curl.
Quoting the reply from GitHub's support with changes in italic:
You're just getting trolled by HTTP and curl.
When you make a PUT request with no body, curl doesn't explicitly set a Content-Length header for that request. However, PUT requests with no Content-Length confuse servers and they respond in weird ways.
Can you please try explicitly setting the Content-Lenght header to 0, or supplying an empty body when making that request (so that curl can set the header for you)? You can accomplish that adding -d "" in your command.