IF I remove
.spec(responseSpec)
from my call, the response prints fine at "FOO". If I include the builder, the response prints an empty string (even though the test is passing). Anyone know why, or how to fix this? I would like to use the builder and print the response of the passing test.
public void getCirclesId()
{
String endpoint = "getCirclesId";
String url = baseUrl + resourcePath + "/" + circleId;
RequestSpecification given = given().header("Authorization", RestTest.BEARER_TOKEN);
ResponseSpecBuilder specBuilder = new ResponseSpecBuilder();
specBuilder.expectBody("features.priceMonth", is("5.00"));
specBuilder.expectBody("features.priceYear", is("50.00"));
Response response = JsonTest.executeRequestWithSpec(given, url, resource, endpoint, JsonTest.HttpType.GET, specBuilder);
}
...
public static Response executeRequestWithSpec(RequestSpecification given, String url, String resource, String endpoint, HttpType type, ResponseSpecBuilder builder)
{
Response response = null;
try {
switch (type) {
case GET:
response = executeGetRequestWithSpec(given, url, builder);
break;
case POST:
response = executePostRequestWithSpec(given, url, builder);
break;
case PUT:
response = executePutRequestWithSpec(given, url, builder);
break;
case DELETE:
response = executeDeleteRequestWithSpec(given, url, builder);
break;
}
System.out.println(resource + " - " + endpoint + ": " + response.print());
} catch (AssertionError e) {
RestTest.failCount++;
System.err.println(resource + " - " + endpoint + " Error: " + e.getMessage());
}
return response;
}
private static Response executeGetRequestWithSpec(RequestSpecification given, String url, ResponseSpecBuilder builder)
{
ResponseSpecification responseSpec = builder.build();
Response response = given.when().get(url + ".json").then().assertThat().statusCode(200).spec(responseSpec).extract().response();
System.out.println("FOOOO" + response.print());
return response;
}
Are you using the latest version of REST Assured (currently 2.3.0)? Otherwise I suggest you to upgrade to this version. There was some problems with response specifications in 2.0.
Related
I am able to get access token for SharePoint from accounts.accesscontrol.windows.net while I am running my application on a machine which is allowed to connect to external URL.
But when I am running my application on an environment where I can only go via a proxy server, its giving me 401: Permission denied (connect failed) even through I have added the proxy code. I am given a ProxyServer URL and port; its of type http.
Please find my code for direct hit below. This is working absolutely fine in open env:
private String getToken(String tenant_id,String client_id, String client_secret, String domain)
{
String resultToken=null;
try {
// AccessToken url
String wsURL = "https://accounts.accesscontrol.windows.net/"+ tenant_id+"/tokens/OAuth/2";
URL url = new URL(wsURL);
URLConnection connection = url.openConnection();
HttpURLConnection httpConn = (HttpURLConnection) connection;
// Set header
httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
httpConn.setRequestMethod("POST");
String jsonParam = "grant_type=client_credentials"
+ "&client_id="+client_id+"#"+tenant_id
+ "&client_secret="+client_secret
+ "&resource=00000003-0000-0ff1-ce00-000000000000/" +domain+".com#"+tenant_id;
System.out.println("TokenRequestString : " + jsonParam);
// Send Request
DataOutputStream wr = new DataOutputStream(httpConn.getOutputStream());
wr.writeBytes(jsonParam);
wr.flush();
wr.close();
// Read the response.
InputStreamReader isr = null;
if (httpConn.getResponseCode() == 200) {
isr = new InputStreamReader(httpConn.getInputStream());
} else {
isr = new InputStreamReader(httpConn.getErrorStream());
}
BufferedReader in = new BufferedReader(isr);
String responseString = "";
String outputString = "";
// Write response to a String.
while ((responseString = in.readLine()) != null) {
outputString = outputString + responseString;
}
// Extracting accessToken from string, here response
// (outputString)is a Json format string
if (outputString.indexOf("access_token\":\"") > -1) {
int i1 = outputString.indexOf("access_token\":\"");
String str1 = outputString.substring(i1 + 15);
int i2 = str1.indexOf("\"}");
String str2 = str1.substring(0, i2);
accessToken = str2;
}
} catch (Exception e) {
accessToken = "Error: " + e.getMessage();
}
return accessToken;
}
Below is my code where I am trying to achieve the same thing through proxy server. This is throwing Permission Denied (401)
private String getToken(String tenant_id,String client_id, String client_secret, String domain)
{
String resultToken=null;
try {
// AccessToken url
String wsURL = "https://accounts.accesscontrol.windows.net/"+ tenant_id+"/tokens/OAuth/2";
URL url = new URL(wsURL);
// via Proxy
Proxy webProxy
= new Proxy(Proxy.Type.HTTP, new InetSocketAddress("internet.xyz.com", 83);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(webProxy);
// Set header
httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
httpConn.setRequestMethod("POST");
String jsonParam = "grant_type=client_credentials"
+ "&client_id="+client_id+"#"+tenant_id
+ "&client_secret="+client_secret
+ "&resource=00000003-0000-0ff1-ce00-000000000000/" +domain+".com#"+tenant_id;
System.out.println("TokenRequestString : " + jsonParam);
// Send Request
DataOutputStream wr = new DataOutputStream(httpConn.getOutputStream());
wr.writeBytes(jsonParam);
wr.flush();
wr.close();
// Read the response.
InputStreamReader isr = null;
if (httpConn.getResponseCode() == 200) {
isr = new InputStreamReader(httpConn.getInputStream());
} else {
isr = new InputStreamReader(httpConn.getErrorStream());
}
BufferedReader in = new BufferedReader(isr);
String responseString = "";
String outputString = "";
// Write response to a String.
while ((responseString = in.readLine()) != null) {
outputString = outputString + responseString;
}
// Extracting accessToken from string, here response
// (outputString)is a Json format string
if (outputString.indexOf("access_token\":\"") > -1) {
int i1 = outputString.indexOf("access_token\":\"");
String str1 = outputString.substring(i1 + 15);
int i2 = str1.indexOf("\"}");
String str2 = str1.substring(0, i2);
accessToken = str2;
}
} catch (Exception e) {
accessToken = "Error: " + e.getMessage();
}
return accessToken;
}
This is the HTTP response I send from my API if there's an error.
return new System.Net.Http.HttpResponseMessage() { StatusCode = (System.Net.HttpStatusCode)System.Net.HttpStatusCode.BadRequest, ReasonPhrase = "Incoming element is null" };
which Postman sees correctly as
"statusCode": 400,
"reasonPhrase": "Incoming element is null",
So the API code is fine, however, when I call the API from my console application the HttpWebResponse using the following
var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://localhost/");
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
httpResponse.StatusCode is OK.
How do I get the returned StatusCode from the API to be accessible/visible in the calling console application.
The httpResponse is the "I am connected" response not the returned response from the API, that was in accessed using
using (var streamReader = new StreamReader(httpResponse.GetResponseStream())) {
string result = streamReader.ReadToEnd();
to stream the result back from the API which was the JSON response being picked up by Postman.
So instead I deserialised the returned JSON into an object and used that to make my validation checks, like so. First my storage class
public class ReturnedJSONModel {
public System.Net.HttpStatusCode statusCode { get; set; }
public string reasonPhrase { get; set; }
}
then this to populate it and handle the response (note this is a Console program so uses Console.WriteLine to report success/failure.
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
if (httpResponse.StatusCode == HttpStatusCode.OK) {
using (var streamReader = new StreamReader(httpResponse.GetResponseStream())) {
string result = streamReader.ReadToEnd();
ReturnedJSONModel objJSON = JsonConvert.DeserializeObject<ReturnedJSONModel>(result);
switch(objJSON.statusCode) {
case System.Net.HttpStatusCode.Accepted:
Console.WriteLine("Success : " + objJSON.reasonPhrase);
break;
case System.Net.HttpStatusCode.BadRequest:
Console.WriteLine("BadRequest : " + objJSON.reasonPhrase);
break;
case System.Net.HttpStatusCode.ServiceUnavailable:
Console.WriteLine("ServiceUnavailable : " + objJSON.reasonPhrase);
break;
default:
Console.WriteLine("Unknown error : " + objJSON.reasonPhrase);
break;
}
}
} else {
Console.WriteLine("Error StatusCode = " + httpResponse.StatusCode);
}
I am having .NET code to call the google api in batch request for getting the message details for multiple Ids. The request I am creating, when run through postman it works perfectly but when run this console app it gives me the Response Status code = 0 and Error Specified value has invalid CRLF characters.\r\nParameter name: value
Can someone please look into this and help me ... I have searched almost everything now but could not get any solution.
Here is my code --
var baseUrl = "/gmail/v1/users/" + _accountID + "/messages/";
RestClient client = null;
RestRequest request = null;
StringBuilder sbBody = null;
for (int j = 0; j < _messageId.Count; j++)
{
msgCount++;
if (msgCount == 1)
{
boundary = "testing_batch";
sbBody = new StringBuilder();
client = new RestClient("https://www.googleapis.com/batch/");
request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "multipart/mixed; boundary=\"" + boundary + "\"");
request.AddHeader("Authorization", "Bearer " + accessToken);
}
sbBody.Append(string.Format("--{0}\n", boundary));
sbBody.Append("Content-Type: application/http\n\n");
sbBody.Append(string.Format("GET {0}{1}\n\n", baseUrl, _messageId[j]));
if (msgCount == 1)
sbBody.Append(string.Format("--{0}--", boundary));
if (msgCount == 1)
{
msgCount = 0;
//request.AddBody(sbBody.ToString());
request.AddHeader("RequestBody", sbBody.ToString());
IRestResponse response = client.Execute(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
//Do nothing for now
}
else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
Console.WriteLine(response.StatusCode);
Console.WriteLine(response.Content);
Console.ReadLine();
break;
}
else
{
Console.WriteLine(response.StatusCode);
Console.WriteLine(response.Content);
Console.ReadLine();
break;
}
}
Following code is aimed at deleting a row from table with given partition key and rowkey. But I get following request/response in fiddler. How can I correct the error?
Request
DELETE https://hireazurestorageacct.table.core.windows.net/mytable(PartitionKey='sample1',%20RowKey='0001')?timeout=20 HTTP/1.1
Accept: application/json;odata=nometadata
x-ms-date: Mon, 08 May 2017 17:59:14 GMT
x-ms-version: 2015-04-05
Accept-Charset: UTF-8
MaxDataServiceVersion: 3.0;NetFx
DataServiceVersion: 1.0;NetFx
If-Match: *
Content-Type: application/json
Authorization: SharedKeyLite hireazurestorageacct:3ZHX8lYBec+/9ytiNQb+JV5dpFkLAieuwB5veMkLVUU=
Host: hireazurestorageacct.table.core.windows.net
Response
HTTP/1.1 403 Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
Content-Length: 299
Content-Type: application/json
Server: Microsoft-HTTPAPI/2.0
x-ms-request-id: a9244f7f-0002-0048-0824-c8afc5000000
Date: Mon, 08 May 2017 17:59:14 GMT
{"odata.error":{"code":"AuthenticationFailed","message":{"lang":"en-US","value":"Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.\nRequestId:a9244f7f-0002-0048-0824-c8afc5000000\nTime:2017-05-08T17:59:14.9335100Z"}}}
Code
public static int DeleteEntity(string storageAccount, string accessKey, string tableName, string partitionkey, string rowkey)
{
string uri = $#"https://{storageAccount}.table.core.windows.net/{tableName}(PartitionKey='{partitionkey}', RowKey='{rowkey}')?timeout=20";
string resource = $#"{tableName}";
// Web request
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "DELETE";
request.Accept = "application/json;odata=nometadata";
request.Headers.Add("x-ms-date", DateTime.UtcNow.ToString("R", System.Globalization.CultureInfo.InvariantCulture));
request.Headers.Add("x-ms-version", "2015-04-05");
request.Headers.Add("Accept-Charset", "UTF-8");
request.Headers.Add("MaxDataServiceVersion", "3.0;NetFx");
request.Headers.Add("DataServiceVersion", "1.0;NetFx");
request.Headers.Add("If-Match", "*");
request.ContentType = "application/json";
// Signature string for Shared Key Lite Authentication must be in the form
// StringToSign = Date + "\n" + CanonicalizedResource
// Date
string stringToSign = request.Headers["x-ms-date"] + "\n";
// Canonicalized Resource in the format /{0}/{1} where 0 is name of the account and 1 is resources URI path
stringToSign += "/" + storageAccount + "/" + resource;
// Hash-based Message Authentication Code (HMAC) using SHA256 hash
var hasher = new HMACSHA256(Convert.FromBase64String(accessKey));
// Authorization header
string strAuthorization = "SharedKeyLite " + storageAccount + ":" + Convert.ToBase64String(hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringToSign)));
// Add the Authorization header to the request
request.Headers.Add("Authorization", strAuthorization);
Thread.Sleep(1000);
// Execute the request
try
{
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (var r = new StreamReader(response.GetResponseStream()))
{
return (int)response.StatusCode;
}
}
}
catch (WebException ex)
{
// get the message from the exception response
using (var sr = new StreamReader(ex.Response.GetResponseStream()))
{
var res = sr.ReadToEnd();
// Log res if required
}
return (int)ex.Status;
}
}
Status 403 means you need to authenticate to access a resource. Any decent server will not give you anything that includes any information about the resource. So you will get the same reply, whether the resource is there or not.
According to your codes, I guess there are something wrong with your authorization token when you use the resource to generate the authorization token.
I suggest you could try below codes to delete the table entity.
Call method:
AzureTableHelper.DeleteEntity("{storageaccount}", "{accesskey}", "{tablename}", "{partitionkey}", "{rowkey}" );
Delete method:
public static int DeleteEntity(string storageAccount, string accessKey, string tableName, string partitionkey, string rowkey)
{
string host = string.Format(#"https://{0}.table.core.windows.net/", storageAccount);
string resource = string.Format(#"{0}", tableName) + string.Format("(PartitionKey='{0}',RowKey='{1}')", partitionkey, rowkey);
string uri = host + resource;
//if you want to check the etag you need firstly get the etag then delete the entity
//string jsonData = "";
//int responseCode = RequestResource(
// storageAccount,
// accessKey,
// resource,
// out jsonData);
//var jsonObject = JObject.Parse(jsonData);
//string time = jsonObject.GetValue("odata.etag").ToString();
//string time = obj.Timestamp;
// Web request
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
request.Method = "DELETE";
request.ContentType = "application/json";
request.Accept = "application/json;odata=nometadata";
request.Headers.Add("x-ms-date", DateTime.UtcNow.ToString("R", System.Globalization.CultureInfo.InvariantCulture));
request.Headers.Add("x-ms-version", "2015-04-05");
request.Headers.Add("If-Match", "*");
request.Headers.Add("Accept-Charset", "UTF-8");
request.Headers.Add("MaxDataServiceVersion", "3.0;NetFx");
request.Headers.Add("DataServiceVersion", "1.0;NetFx");
// Signature string for Shared Key Lite Authentication must be in the form
// StringToSign = Date + "\n" + CanonicalizedResource
// Date
string stringToSign = request.Headers["x-ms-date"] + "\n";
// Canonicalized Resource in the format /{0}/{1} where 0 is name of the account and 1 is resources URI path
stringToSign += "/" + storageAccount + "/" + resource;
// Hash-based Message Authentication Code (HMAC) using SHA256 hash
System.Security.Cryptography.HMACSHA256 hasher = new System.Security.Cryptography.HMACSHA256(Convert.FromBase64String(accessKey));
// Authorization header
string strAuthorization = "SharedKeyLite " + storageAccount + ":" + System.Convert.ToBase64String(hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringToSign)));
// Add the Authorization header to the request
request.Headers.Add("Authorization", strAuthorization);
// Execute the request
try
{
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (System.IO.StreamReader r = new System.IO.StreamReader(response.GetResponseStream()))
{
string jsonResponse = r.ReadToEnd();
return (int)response.StatusCode;
}
}
}
catch (WebException ex)
{
// get the message from the exception response
using (System.IO.StreamReader sr = new System.IO.StreamReader(ex.Response.GetResponseStream()))
{
string res = sr.ReadToEnd();
// Log res if required
}
return (int)ex.Status;
}
}
I'm trying to save a PDF from QBO however I'm stuck on this bit:
How do i get the IConsumerRequest to return a stream instead of a string? ReadBody only seems to send string rather than binary data...
IConsumerRequest conReq = oSession.Request();
conReq = conReq.Get().WithRawContentType("application/pdf");
string outURL = base_url + "invoice-document/v2/" + realmId + "/" + customerInvoicesWithinDateRange[0].Id.Value;
conReq = conReq.ForUrl(outURL);
conReq = conReq.SignWithToken();
string serviceResponse = conReq.ReadBody();
Thanks
instead of conReeq.ReadBody(), you can do this:
conReq.ToWebResponse().GetResponseStream();
in fact, ReadBody() is simply an extension method on IConsumerRequest, defined as:
public static string ReadBody(this IConsumerRequest request)
{
HttpWebResponse response = request.ToWebResponse();
return response.ReadToEnd();
}