I am trying to connect to a Vertex tax database using PowerBuilder 11.1 and am having problems with the following code.
I think I am connecting correctly since the return codes for ls_status_text = loo_xmlhttp.StatusText is 200 and ll_status_code = loo_xmlhttp.Status is OK.
When I get the return value from the ls_response_text = loo_xmlhttp.ResponseText code the return value is the MOTW message.
I am expecting the following code to send the ls_get_url (which contains the xml to be sent to vertex) and receive a large xml in return with calculated tax rates based off the ls_get_url xml. What I am getting is ls_status_text = 'OK' and ll_Status_code = 200 ( anything >300 is a problem).
// Get request
loo_xmlhttp.open ("GET",ls_get_url , false)
loo_xmlhttp.send()
//Get response
ls_status_text = ''
ls_status_text = loo_xmlhttp.StatusText
ll_status_code = loo_xmlhttp.Status
after the above block of code runs successfully the following code runs:
if ll_status_code >= 300 then
MessageBox("HTTP POST Request Failed", ls_response_text)
else
//Get the response we received from the web server
ls_response_text = loo_xmlhttp.ResponseText
MessageBox("POST Request Succeeded", ls_response_text)
end if
I get the "POST Request Succeeded" messagebox but the ls_response_text contains the Mark Of The Web syntax.
Do you have any ideas that can help me along?
Thanks!
String ls_get_url, ls_post_url
String ls_post_variables, ls_response
String ls_response_text, ls_status_text
long ll_status_code
OleObject loo_xmlhttp
//include parameters on the URL here for get parameters
ls_get_url = 'http://10.1.1.65:8095/vertex-ui/vertextcc.jsp'
try
//Create an instance of our COM object
loo_xmlhttp = CREATE oleobject
loo_xmlhttp.ConnectToNewObject( 'Microsoft.XMLHTTP')
// Get request
loo_xmlhttp.open ("GET",ls_get_url , false)
loo_xmlhttp.send()
//Get response
ls_status_text = ''
ls_status_text = loo_xmlhttp.StatusText
ll_status_code = loo_xmlhttp.Status
//Check HTTP Response code for errors
if ll_status_code >= 300 then
MessageBox("HTTP GET Request Failed", ls_response_text)
else
//Get the response we received from the web server
ls_response_text = loo_xmlhttp.ResponseText
MessageBox("GET Request Succeeded", ls_response_text)
end if
ls_post_url = 'http://10.1.1.65:8095/vertex-ui/vertextcc.jsp'
ls_post_variables = "I add my custom xml here - I can run it in the vertex software and the xml executes fine"
loo_xmlhttp.open ("POST",ls_post_url, false)
loo_xmlhttp.send(ls_post_variables)
//Get response
ls_status_text = loo_xmlhttp.StatusText
ll_status_code = loo_xmlhttp.Status
//Check HTTP Response code for errors
if ll_status_code >= 300 then
MessageBox("HTTP POST Request Failed", ls_response_text)
else
//Get the response we received from the web server
ls_response_text = loo_xmlhttp.ResponseText
MessageBox("POST Request Succeeded", ls_response_text)
end if
loo_xmlhttp.DisconnectObject()
catch (RuntimeError rte)
MessageBox("Error", "RuntimeError - " + rte.getMessage())
end try
There's an On Demand Vertex service. I hit the .../vertex-ui/vertextcc.jsp address on port 80 and got a login prompt. So it appears you need to Post the login data before you start shoving XML at it. I couldn't look any farther as I don't have an account. I don't know what the server would give you after you log in, but if it's a page you can paste XML into, you could install Fiddler and see exactly what belongs in the Post. Fiddler will also show you what Microsoft XMLHTTP is posting and what the server is sending back.
Related
We have an airtable database of over 24000 records. These records are websites, and many now have errors in them (missing "/", extra space...). We are trying to detect the websites that have these errors before manually fixing them.
What we have tried
So far, we have used the fetch method to call each URL and report back on the error status . This is the script we have used:
const inputConfig = input.config();
const url = inputConfig.url;
let status;
try {
const response = await fetch(url);
status = response.status; } catch (error) {
status = 'error'; }
output.set('status', status);
Issues we ran into
The script won't follow redirects, so it reports "error" back if there is a redirect even if the URL is working.
The output now is either "200" meaning the URL works, or "error". We don't get the actual response code of the error, which we ideally would like to get.
Any help would be appreciated! Thanks
There's some nuance to how fetch works. If you review Mozilla's documentation they say:
The Promise returned from fetch() won't reject on HTTP error status even if the response is an HTTP 404 or 500. Instead, as soon as the server responds with headers, the Promise will resolve normally (with the ok property of the response set to false if the response isn't in the range 200–299), and it will only reject on network failure or if anything prevented the request from completing.
So you have to do an extra check in your code to determine if the request was successful or not and throw your own error. In your case, you don't necessarily need to throw an error at all and can just rely on ok property of the response.
const config = input.config();
const url = config.url;
let status = null;
const response = await fetch(url);
if(response.ok) {
status = response.status
} else {
status = 'error'
}
output.set('status', status);
I'm trying to display errors in a friendly way, but I'm always getting the errors stack trace with console logs that I want to get rid of.
The idea is to create a Lead in our platform using any source, for example, Google Sheets.
When an invalid email is provided in the lead and posted to our API, I'm getting the expected message I want to display followed by the stack trace.
My custom error message is
INVALID FORMAT for email. Object didn't pass validation for format email: as1#mail.
But this is what I'm getting:
INVALID FORMAT for email. Object didn't pass validation for format email: as1#mail. What happened: Starting POST request to https://cosmo-charon-production.herokuapp.com/v1/lead/vehicle Received 500 code from https://cosmo-charon-production.herokuapp.com/v1/lead/vehicle?api-key=gIBp04HVdTgsHShJj6bXKwjbcxXTogsh after 62ms Received content "{"code":"SCHEMA_VALIDATION_FAILED","message":"Request validation failed: Parameter (lead) failed sch" INVALID FORMAT for email. Object didn't pass validation for format email: as1#mail. Console logs:
Image showing error displayed in Zapier
I've added a middleware for ErrorHandling into afterResponse, just as one of the examples provided in Zapier docs.
The function analyzeAndParse() receives an error object from the API and returns a string with the error message translated in a friendly way
const checkForErrors = (response, z) => {
// If we get a bad status code, throw an error, using the ErrorTranslator
if (response.status >= 300) {
throw new Error(analyzeAndParse(response.json))
}
// If no errors just return original response
return response
}
This is the code that creates a Lead in our platform, making a request to our API.
function createLead (z, bundle) {
const industry = bundle.inputData.industry
// add product to request based on the inputFields
leadType[industry].addProductFields(bundle.inputData)
const requestOptions = {
url: `${baseUrl}lead/${_.kebabCase(industry)}`,
method: 'POST',
body: JSON.stringify(checkSourceForCreate(bundle.inputData)),
headers: {
'content-type': 'application/json'
}
}
return z.request(requestOptions).then((response) => {
if (response.status >= 300) {
throw new Error(analyzeAndParse(response.content))
}
const content = JSON.parse(response.content)
if (content && content.leads) {
// get only the last lead from the list of leads
content.lead = content.leads[0]
delete content.leads
}
return content
})
}
Any ideas?
Thanks!
I want to intercept requests in my application and one of the scenarios I have come across is that - due to nature of the application some of the services have same request endpoint different payload though and I want to send back different responses at different occurrence. Is there a way to assign order to the intercepted request and send a specific response as per the sequence? or any other mechanism to tell browser-mob that example - for this url with this payload send this response? Because if it is the same url then responses are overridden by the last intercepted request.
I have already tried request with url and contents contains. Check the if condition in code below.
proxy.addRequestFilter((request, contents, messageInfo) -> {
String content = null;
try {
content = URLDecoder.decode(contents.getTextContents(), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if (request.getUri().contains(endpoint) && (content != null && content.contains(contentContains))) {
//Use DefaultFullHttpResponse for posting the json body
final HttpResponse httpResponse = new DefaultFullHttpResponse(request.getProtocolVersion(),
statusCode);
//Close the connection so it doesn't pass through
httpResponse.headers().add("CONNECTION", "Close");
//Specify the content-type and charset
httpResponse.headers().add("Content-Type", "application/json; charset=UTF-8");
//replace the body
HttpObjectUtil.replaceTextHttpEntityBody((FullHttpMessage) httpResponse, response);
return httpResponse;
}
return null;
});
Actual - If the two request have same endpoint the last intercepted request overrides the response I want to send back.
Expected- Some mechanism where Bowsermob is able to register different responses for the request with same end point and send back different response.
I am newbie to web service. Due to requirement I have to send a file[most probably in txt format] to server through REST web service.
I am getting the exception like below.
MessageBodyWriter not found for media type=application/json, type=class gvjava.org.json.JSONObject, genericType=class gvjava.org.json.JSONObject.
Here is my web service method.
#Path("{c}")
#POST
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public String convert(#PathParam("c") JSONObject object) throws JSONException {
String result = "";
return "<ctofservice>" + "<ctofoutput>" + result + "</ctofoutput>" + "</ctofservice>";
}
Now client code is like below
JSONObject data_file = new JSONObject();
data_file.put("file_name", uploadFile.getName());
data_file.put("description", "Something about my file....");
data_file.put("file", uploadFile);
Client client = ClientBuilder.newClient();
webTarget = client.target(uploadURL).path("ctofservice").path("convert");
Response value = webTarget.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.entity(data_file,MediaType.APPLICATION_JSON_TYPE),
Response.class);
Please help me with this.
Thanks in advance.
------------------------------------------------------------------------
As suggested by peeskillet in the answer below, I tried to send file through multipart. Still I am facing exception of no octet stream found.
Below is my rest api
#Path("{c}")
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response convert(#FormDataParam("file") FormDataContentDisposition file) {
String result = "";
Some operation with attached parameter ...
return Response.status(200).entity(result).build();
}
Here is my test client
FormDataMultiPart multiPart = new FormDataMultiPart();
multiPart.setMediaType(MediaType.MULTIPART_FORM_DATA_TYPE);
FileDataBodyPart fileDataBodyPart = new FileDataBodyPart("file",
uploadFile,MediaType.APPLICATION_OCTET_STREAM_TYPE);
multiPart.bodyPart(fileDataBodyPart);
Client client = Client.create();
WebResource webResource = client
.resource(uploadURL).path("ctofservice");
ClientResponse response = webResource.accept("application/json")
.post(ClientResponse.class,multiPart);
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ response.getStatus());
}
And I am getting the exception below
I am not able to understand why I need to send data as MediaType.APPLICATION_OCTET_STREAM_TYPE ? As I have used multipart as media type before ...
I appreciate your help..
Without needing to configuring anything else, the easiest way to get around this is to just use a String instead of the actual JSONObject (i.e. just passing toString())
.post(Entity.json(data_file.toString()))
The problem with using JSONObject is that there is no provider that knows how to handle the conversion. You will have the same problem on the server side, where there is no provider to handle the conversion to JSONObject. So you will need to just do
#POST
public Response post(String json) {
JSONObject jsonObject = new JSONObject(json);
}
If you really want to be able to just use JSONObject without needing to use a String, then you should check out this post.
As an aside, this is not valid JSON (it's XML)
"<ctofservice>" + "<ctofoutput>" + result + "</ctofoutput>" + "</ctofservice>"
but you are saying that the endpoint returns JSON
I'm using the DotNetOpenAuth framework which has been great to get up to speed with consuming data.
I'm using it to talk to LinkedIn and am having trouble figuring out the correct approach to posting/sharing information to the site. Here is the reference I am using - http://developer.linkedin.com/documents/share-api
When I execute the below code I always get the below error responses;
Error occurred while sending a direct message or getting the response.
The remote server returned an error: (400) Bad Request.
I am using Oauth v1.0a.
Here is my code;
try
{
HttpDeliveryMethods resourceHttpMethod = HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest;
string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><share><comment>83% of employers will use social media to hire: 78% LinkedIn, 55% Facebook, 45% Twitter [SF Biz Times] http://bit.ly/cCpeOD</comment>";
xml += "<content><title>Survey: Social networks top hiring tool - San Francisco Business Times</title>";
xml += "<submitted-url>http://sanfrancisco.bizjournals.com/sanfrancisco/stories/2010/06/28/daily34.html</submitted-url>";
xml += "<submitted-image-url>http://images.bizjournals.com/travel/cityscapes/thumbs/sm_sanfrancisco.jpg</submitted-image-url>";
xml += "</content><visibility><code>anyone</code></visibility></share>";
var multiparts = new List<MultipartPostPart>();
MultipartPostPart part = MultipartPostPart.CreateFormPart("body", xml);
part.PartHeaders[HttpRequestHeader.ContentType] = "application/xml";
multiparts.Add(part);
var resourceEndpoint = new MessageReceivingEndpoint("http://api.linkedin.com/v1/people/~/shares", resourceHttpMethod);
HttpWebRequest request = consumer.PrepareAuthorizedRequest(resourceEndpoint, accessToken, multiparts);
request.ServicePoint.Expect100Continue = false;
IncomingWebResponse response = consumer.Channel.WebRequestHandler.GetResponse(request);
this.resultsBox.Text = response.GetResponseReader().ReadToEnd();
}
catch (Exception ex)
{
}
Thanks
Forgot to write back on this, talking to someone from a vintage google newsgroup I got the direction I needed but wanted to verify the solution before posting.
The big thing I was screwing up on was adding the multipart data prior to sending the request data as opposed to constructing the request myself and writing the new content to the stream.
I'm new to using OAuth and REST so I don't know all the ins and outs, suffice to say I've validated this code against both the LinkedIn and Twitter REST APIs.
Here is the new CODE;
try
{
Encoding encoder = Encoding.ASCII;
HttpDeliveryMethods resourceHttpMethod = HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest;
byte[] bytes = encoder.GetBytes(xd.OuterXml.ToString());
var resourceEndpoint = new MessageReceivingEndpoint(ResourceURL, resourceHttpMethod);
HttpWebRequest request = _consumer.PrepareAuthorizedRequest(resourceEndpoint, _manager.AccessToken);
request.ServicePoint.Expect100Continue = false;
request.Method = "POST";
request.ContentLength = bytes.Length;
request.ContentType = "application/xml";
using (System.IO.Stream requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
IncomingWebResponse response = _consumer.Channel.WebRequestHandler.GetResponse(request);
ret = true;
}
catch (Exception ex)
{
_Logger.Error(OpenLogger.FormatException(ex));
}