I have a web service API call that returns BOTH:
First part is document metadata in the form of JSON (application/JSON)
and in the same response returns PDF bytes (application/pdf)
If HttpURLConnection.setRequestProperty("Accept", "application/JSON) is set only the first part is returned with is the metadata in the form of JSON.
If HttpURLConnection.setRequestProperty("Accept", "application/pdf) is set then only the later part of the response is returned in the form of PDF, starting with %PDF and ending with EOF.
The response indeed contains the metadata (first part) and PDF (later part). I can get one part, or the other by the setting above.
[b]But in the single/same call, I need to get both metadata (JSON) and PDF, and I am not able to do so[/b]
I tried with the following and it does not return any result (the result is empty).
HttpURLConnection.setRequestProperty("Accept", "application/JSON;application/pdf") - this did not work.
The following configurations also returned empty results:
HttpURLConnection.setRequestProperty("Accept", "application/")
HttpURLConnection.setRequestProperty("Accept", "/*")
Instead of Accept, I also tried using "Content-Type, with the settings below, and the settings below return no (empty) value.
HttpURLConnection.setRequestProperty("Content-Type", "application/")
HttpURLConnection.setRequestProperty("Content-Type", "/*")
The code is similar to:
enter code herehttpURLConnection.setRequestProperty("Accept", "??? what setting to put to get both JSON and PDF");
enter code hereBufferedReader br = new BufferedReader(new InputStreamReader((httpURLConnection.getInputStream())));
enter code hereStringBuffer sb=new StringBuffer();
enter code hereString line;
enter code herewhile ((line = brToGetDocMetadata.readLine()) != null) {
enter code here sb.append(line);
enter code here}
enter code herelogger.debug(sb.toString());
Questions:
What do I need to do to get both metadata (JSON) and PDF in the same call returned to me?
The StringBuffer gets either JSON, or PDF bytes but I need to get both.
Should I try Content-Type instead of Accept?
Related
I have a SoapUI REST (i.e. non-SOAP) mock service that returns a response for a POST request.
The request and response both contain JSON content.
At the moment, I can get it to return a static response and that works fine, but I want some of the values in the response to be dynamically sourced from the request.
So if I have this request:
{
"the_request":{
"abc":"123",
}
How can I get the value of "abc" copied in the response?
Investigation has lead me to believe I can do this via including a variable in the response, something like:
Response:
{
"the_response":{
"value_from_request":"${#MockResponse#Request#the_request#abc}",
"other":"stuff",
}
And then implementing a script to populate the variable in the response, via the Script tab.
How can I then populate this with data from the request?
Currently SoapUI just generates an empty value
"value_from_request":"",
Tried using mockRequest.requestContent in the Script tab, but have not found how to obtain the "123" value from it.
OK, worked this out. So the response message can simply reference a variable in the requestContext like so:
Response:
{
"the_response":{
"value_from_request":"${the_value}",
"other":"stuff",
}
And a groovy script can be used to parse the JSON request content and populate "the_value" or whatever you like in the requestContext:
// Parse the JSON request.
def requestBody = new groovy.json.JsonSlurper().parseText(mockRequest.getRequestContent())
// Set up "the_value" from the request message.
requestContext.the_value = requestBody.the_request.abc
// Bit of logging so can see this in the "script log" tab.
log.info "Value extracted from request: ${requestContext.the_value}"
I think the script should be like this
def requestBody = new groovy.json.JsonSlurper().parseText(mockRequest.getRequestContent())
context.setProperty("the_value",requestBody.the_request.abc)
I am using Angular4 with TypeScript version 2.2.2
My web app is running fine when I call JSON with Filters but my NativeScript app fails when I call the Filter Values as an Object but works fine when I call filter values as a string.
Error Response with status: 200 for URL: null
THIS WORKS
https://domainname.com/api/v1/searchevents?token=057001a78b8a7e5f38aaf8a682c05c414de4eb20&filter=text&search=upcoming
If the filter value and search value is STRING it works whereas if they are objects as below, it does not work
THIS DOES NOT WORK
https://api.domainname.com/api/v1/searchevents?token=057001a78b8a7e5f38aaf8a682c05c414de4eb20&filter={"limit":"12","skip":"0"}&search={"search":"","latitude":"","longitude":"","categories":"","address":"","type":"upcoming"}
The Code I used is below
getData(serverUrl, type, skip_limit) {
console.log(serverUrl);
let headers = this.createRequestHeader();
let token_value = localStorage.getItem('access_token')
let url;
var filter;
filter = '{"limit":"10","skip":"0"}'
url = this.apiUrl + serverUrl + '?token=' + token_value + '&filter=' + filter
return this.http.get(url, { headers: headers })
.map(res => res.json());
}
The URL as formed above for the API is fine and works fine. Yet the error comes Error Response with status: 200 for URL: null
CAN ANYONE HELP ME SOLVE THIS?
Looks like the issue is the "filter" values are of different type and from what you mentioned as what worked, your service is expecting a string and not an object/array. So it fails to send the proper response when it gets one. With an object in the URL, you may have to rewrite the service to read it as an object (parse the two attributes and get them individually)
To make it simple, you can make these two as two different variables in the URL. like below,
https://api.domainName.in/api/v1/oauth/token?limit=10&skip=0
Be more precise in whats happening in your question,
1) Log the exact URL and post it in the question. No one can guess what goes in "text" in your first URL.
2) Your URL which you mentioned as worked have "token" as part of path, but in the code, its a variable which will have a dynamic value from "token_value".
3) Post your service code. Especially the signature and input parsing part.
Got the solution:
All you have to do is encode the Filter and Search Parameters if it is an Object or Array using Typescript encodeURI()
var filter = '{"limit":"12","skip":"0"}'
var search = '{"search":"","latitude":"","longitude":"","categories":"","address":"","type":"upcoming"}'
var encoded_filter = encodeURI(filter);
var encoded_search = encodeURI(search);
url = this.apiUrl+serverUrl+'?token='+token_value+'&filter='+encoded_filter+'&search='+encoded_search
I'm trying to extract a SessionId from the XML which is returned from a SOAP API.
I've read through the Postman documentation (several times over) but it wasn't the most helpful in achieving my goal.
What was suggested in a few blogs was to convert the XML to JSON, and then pick out the token and it's value from there, but that didn't help either.
I used the following in my Test:
var jsonObject = xml2Json(responseBody);
postman.setGlobalVariable("Session_Id", jsonObject.SessionID);
The above created the variable "Session_Id" but didn't actually assign a value to it. I'm stumped.
I'm definitely retrieving the data from the API, and it's viewable in Postman's "Body" Response.
To extract a variable from XML using Postman, first convert your XML to JSON, using the xml2Json converter method:
var responseJson = xml2Json(responseBody);
(Where "responseBody" is your xml body.)
Then use the console.log method to output your JSON data, as such:
console.log(responseJson);
Be sure to have followed this tutorial on Enabling Chrome Dev Tools in Postman
Inside your Test Runner, run the test, then right click and "Inspect" anywhere in the Runner. Select the "Console" tab once Chrome's Dev Tools launch. Expand the "Object" part.
Then drill-down (expand) until you see the Property whose data you need.
Thereafter, set the variable by appending each drill-down level to the parameter you want:
postman.setGlobalVariable("Session_Id", responseJson.UserSessionToken.SessionID);
In this case, "responseJson" is the object, "UserSessionToken" was the next level in the drill-down, and SessionId was the parameter I needed within that.
Note: This answer was the correct solution before v7.15.0 of postman. For versions later than this, the accepted answer may not work.
Since Postman v7.15.0 the accepted answer did not work for me (it used to before the update). You have to put the path segments into square brackets.
For example, in the following XML response:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<QuotesPrivateResponse>
<lease-service>
<duration-in-months>24</duration-in-months>
</lease-service>
</QuotesPrivateResponse>
to retrieve the value duration-in-months:
var response = xml2Json(responseBody);
var duration = response["QuotesPrivateResponse"]["lease-service"]["duration-in-months"];
pm.environment.set("duration", duration);
My strong suspicion is that this behaviour is caused when any of the element names contain hyphens.
Postman v7.20.1
I'd like to add my answer since above there are a couple of details that took me a while to solve:
how to cope with a multipart SOAP response
how to manage a JSON object
responseBody definition
Here's the first lines of my XML response to analyze:
------=_Part_694527_1470506002.1584708814081
Content-Type: application/xop+xml;charset=UTF-8;type="text/xml"
Content-Transfer-Encoding: 8bit
Content-ID:
<e3bd82ac-d88f-49d4-8088-e07ff1c8d407>
<?xml version="1.0" encoding="UTF-8" ?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header/>
<env:Body>
<ns2:GenericResponse xmlns:ns2="http://XXXXXXXX">
<ns2:Service IdcService="XXXXXXXX">
<ns2:Document>
<ns2:Field name="XXXXXXXX:isSetDefault">1</ns2:Field>
<ns2:Field name="XXXXXXXX">CHECKIN_UNIVERSAL</ns2:Field>
After I noticed it was a multipart I've ended up with this Postman Test:
var response = pm.response.text();
var responseBody = response.substr(response.indexOf('<env:'));
pm.test("The body of the response is a valid XML", function () {
pm.expect(xml2Json(responseBody)).to.exist;
});
pm.test("UCM file upload checkin succesfull", function(){
var responseJson = xml2Json(responseBody);
var JsonFields = (responseJson['env:Envelope']['env:Body']['ns2:GenericResponse']['ns2:Service']['ns2:Document']['ns2:Field']);
JsonFields.forEach( field => {
if (field.name == 'StatusMessage'){
console.log("Field = " + field.name);
pm.expect(field.text().to.include("Successfully checked in"));
}
});
});
I have created a WebAPI project to help capture statements from a TinCan learning course but I am having extreme difficulty in retrieving any of the Request payload details. Within this payload I pass the whole statement that I am trying to capture but upon trying to read using:
var test = Request.Content.ReadAsFormDataAsync().Result.ToString();
I get the following error message:
No MediaTypeFormatter is available to read an object of type 'FormDataCollection' from content with media type 'application/json'.
I have tried Converting the result object to JSON to overcome this problem but it has not been any use. Do I need to configure json somewhere in the configuration? I have tried adding
var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
and also:
var jsonFormatter = config.Formatters.JsonFormatter;
config.Formatters.Insert(0, jsonFormatter);
to my WebApiConfig.cs file as answered in another question of how to return json but I cannot seem to pass this error. I have also set config.formatter to accept application/json but this also has not worked
CONTROLLER CODE
public void Put([FromBody]string statementId)
{
var test = Request.Content.ReadAsFormDataAsync().Result;
System.Diagnostics.EventLog.WriteEntry("Application", "/xAPI/PUT has been called", System.Diagnostics.EventLogEntryType.Error);
}
From the error message you have provided, it seems like request content is in application/json. ReadAsFormDataAsync() can only read content of type application/x-www-form-urlencoded.
In this case, you can use ReadAsAsync<> if you have the type you want to be deserialized defined or simply use ReadAsStringAsync<> if you just want to read the content as a string.
I would like to get the response of a website that has results posted by a form. I've tried using WebClient, WebRequests, etc.
Current Code:
using (var client = new WebClient())
{
var buffer = client.UploadValues("https://secure.monroecc.edu/pls/bpr1/bwzkfcls.P_GetCrse", "POST", vals);
return Encoding.UTF8.GetString(buffer, 0, buffer.Count());
}
Also pretty sure that the current code isn't wrong it's just missing something. When I do get the response of the website it's wrong, it's the page where you would fill out the form.
If you try to GET the website it results in this error on the website itself (without posting the variables that go along with it):
VARIABLES IN FORM NOT IN PROCEDURE:
NON-DEFAULT VARIABLES IN PROCEDURE NOT IN FORM: TERM_IN,SEL_SUBJ,SEL_CRSE,SEL_TITLE,BEGIN_HH,BEGIN_MI,BEGIN_AP,SEL_DAY,SEL_PTRM,END_HH,END_MI,END_AP,SEL_CAMP,SEL_SCHD,SEL_SESS,SEL_INSTR,SEL_ATTR,SEL_LEVL,SEL_INSM
DAD name: bpr1
PROCEDURE : bwzkfcls.P_GetCrse
URL : http://secure.monroecc.edu:63500/pls/bpr1/bwzkfcls.P_GetCrse
PARAMETERS :
===========
Here's an image of the request being sent. (Viewing using Chrome)
I know that the website usses oracle PLSQL but again that doesn't seem to help me with retrieving the results of the search.
I posted the form using the following code:
private void Run(string[] args)
{
NameValueCollection vals = new NameValueCollection();
vals.Add("TERM_IN", "");
vals.Add("SEL_SUBJ", "");
vals.Add("SEL_CRSE", "");
vals.Add("SEL_TITLE", "");
vals.Add("BEGIN_HH", "");
vals.Add("BEGIN_MI", "");
vals.Add("BEGIN_AP", "");
vals.Add("SEL_DAY", "");
vals.Add("SEL_PTRM", "");
vals.Add("END_HH", "");
vals.Add("END_MI", "");
vals.Add("END_AP", "");
vals.Add("SEL_CAMP", "");
vals.Add("SEL_SCHD", "");
vals.Add("SEL_SESS", "");
vals.Add("SEL_INSTR", "");
vals.Add("SEL_ATTR", "");
vals.Add("SEL_LEVL", "");
vals.Add("SEL_INSM", "");
using (var client = new WebClient())
{
var buffer = client.UploadValues("https://secure.monroecc.edu/pls/bpr1/bwzkfcls.P_GetCrse", "POST", vals);
Console.WriteLine(Encoding.UTF8.GetString(buffer, 0, buffer.Count()));
//Console.Read();
}
}
It returns a 200 status code and valid html indicating that the form was received properly. However, since none of the values are correct the returned page says that there is a missing form element that must be included (NAME NOT FOUND FOR PIDM: )
The parameter mismatch error you are receiving means that the parameters you are passing in are not the ones that the stored procedure expects. You'll need to get an exact list of the parameters and expected values first, then you can just plug them in and this should work. Unfortunately the page returns a 200 status code so you'll have to parse out somehow whether there was an error or not.
Use a GET request instead of a POST.
You are asking for a page that follows a form to give you a result set when it never actually receives the form variables that would make the result possible.
Your variable vals which should pass the set of variables never does.
VARIABLES IN FORM NOT IN PROCEDURE:
NON-DEFAULT VARIABLES IN PROCEDURE NOT IN FORM: TERM_IN,SEL_SUBJ,SEL_CRSE,SEL_TITLE,BEGIN_HH,BEGIN_MI,BEGIN_AP,SEL_DAY,SEL_PTRM,END_HH,END_MI,END_AP,SEL_CAMP,SEL_SCHD,SEL_SESS,SEL_INSTR,SEL_ATTR,SEL_LEVL,SEL_INSM
This response error says that it never received any of the variables listed. I would trace back in your code to the location were you name and assigned your list of variables to the Collection vals. Check for proper spellings and proper assignment.