Blue Prism web api service - Cannot send a content-body with this verb-type - blueprism

I'm having some trouble getting a GET Action with body to work in BluePrism (using web api service).
It seems that when I try to include an Action that sends a GET with body when I reach that stage this error gets thrown:
Internal : Unexpected error Cannot send a content-body with this verb-type.
What I've tried:
Using a different verb-type / passing parameters in the query instead of the body, unfortunately i don't have control over the endpoint i'm trying to reach so this didnt work as it only accepts a GET containing data in the body
Using BluePrism HTTP Utility to send the call, this has the same problem as the Web API Service
Compiling the body via code instead of using a template
I haven't been able to find anyone that made it work in BluePrism and there doesn't seem to be much documentation on this issue in BluePrism so any help would be appreciated.
Thanks!

.NET's WebRequest class that Blue Prism uses under the hood to conduct
these requests will not allow you to send a request body with any GET
request. There is no (documented) way to overcome this limitation.
While other related answers on Stack
Overflow correctly state
that there exists no such prohibition on including request bodies with
GET requests per RFC
9110ยง9.3.1, it is
very unusual for a production-grade service to require that the request
itself include anything in the request body. It's also possible that
intermediaries like HTTP proxies may strip or otherwise mangle the request
body in transit anyway.
There is no out-of-the-box way to force the .NET Framework (which Blue
Prism uses) to send GET requests with a request body. If you're able,
you can install
WinHttpHandler
and implement it as a drop-in replacement for HTTPRequest (this SO
thread will help).
Because this type of solution requires the install of a new library, it's
important to consider the caveats of doing so:
Blue Prism's support for external DLLs is unstable at best, and there's
no guarantee it will even import correctly to begin with. Vendor support
for this type of setup is, anecdotally, limited to nonexistent (and
rightfully so, IMO).
If you're able to successfully implement the functionality described
with WinHttpHandler, you'll need to install it on every Blue Prism
developer's machine and runtime resource in all your environments
(development/SIT/UAT/production). For some organizations, strict IT
security posture makes this rather impractical or outright infeasible.

I managed to get it working using a code block containing C# code and using Reflection, here is a my GET method:
public string GetWithBodyAndAuth(string uri, string data, string token, out int statusCode)
{
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Headers.Add("Authorization", "Basic " + token);
request.ContentType = "application/json; charset=utf-8";
request.Method = "GET";
request.Accept = "application/json";
var type = request.GetType();
var currentMethod = type.GetProperty("CurrentMethod", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(request);
var methodType = currentMethod.GetType();
methodType.GetField("ContentBodyNotAllowed", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(currentMethod, false);
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(data);
}
var response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
statusCode = ((int)response.StatusCode);
return reader.ReadToEnd();
}
It's a bit of a hack and can't say if it'll be supported in the future, but for BluePrism 6.9 this allows you to send GET requests containing a body.
It has the advantage of not requiring any external DLLs, this is the import list:

Related

Building out first client using ServiceStack

I'm trying out ServiceStack for connecting to an OAuth2 / JSON service. (C#)
First I'm struggling to find a good example of this out there as it appears most examples are using v3 of ServiceStack. So if you're aware of a good example to work off of that would be great.
I'm working with the example code on SO question: ServiceStack intercept requests before they are sent client side
But I'm having a hard time finding the correct NUGET packages to install.
I've got NUGET packages ServiceStack, ServiceStack.Client, ServiceStack.Common and ServiceStack.Authentication.OAuth2, ServiceStack.HttpClient.
I'm still not able to resolve:
request.ContentType = ServiceStack.Common.Web.ContentType.Json;
Namespace name "web" does not exist in the namespace ServiceStack.Common
and
request.Headers.Add(ApiCustomHttpHeaders.UserId, "1");
ApiCustomHttpHeaders does not exist in the current context.
As the linked answer indicates you need to use RequestFilter in ServiceStack v4+. The MimeTypes are available in MimeTypes static class, otherwise you can use the JSON Content-Type application/json, e.g:
client.RequestFilter = req =>
{
// ContentType still null at this point so we must hard code it
// Set these fields before trying to create the token!
request.ContentType = MimeTypes.Json;
request.Date = DateTime.Now;
var secret = "5771CC06-B86D-41A6-AB39-9CA2BA338E27";
var token = ApiSignature.CreateToken(request, secret);
req.Headers.Add(ApiCustomHttpHeaders.UserId, "1");
req.Headers.Add(ApiCustomHttpHeaders.Signature, token);
};

javax.microedition.pki Certificate Failed Verification

I'm trying to read in a JSON reply from the Google Sheets API in a Java ME MIDP application. I've tried the following with other addresses and it receives their content fine but the actual API I want to use is Sheets and it always returns an "Certificate Failed Verification" exception.
HttpConnection c = null;
InputStream is = null;
StringBuffer str = new StringBuffer();
try
{
c = (HttpsConnection)Connector.open(urlstring);
c.setRequestMethod(HttpConnection.GET);
c.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
c.setRequestProperty("User-Agent","Profile/MIDP-2.1 Configuration/CLDC-1.1");
is = c.openInputStream();
int len = (int)c.getLength();
int ch;
while ( (ch = is.read() ) != -1)
{
str.append((char)ch);
}
}
catch( Exception e ){ alert( ""+e ); }
return str.toString();
Connector.open() implicitly returns a HttpsConnection if the URL starts with Https so it should still work.
An example of a HTTPS request
https://jsonplaceholder.typicode.com/posts/1
Which won't work but the above also allows for HTTP connections
http://jsonplaceholder.typicode.com/posts/1
Which will work.
Google Sheets however requires HTTPS and thus is not obtainable via the above code. How can I make a GET request over HTTPS to the sheets API? Thank you.
I had a similar problem when implementing an online highscore system for one of our games. It would fetch highscores fine on some phones but didn't work on other phones. The explanation:
Some phones have their own built-in "MIME-type checker". When you call (HttpConnection)Connector.open(urlstring) the phone expects a text/html response. When it instead gets a application/json (or other) response, the phone gives its own "Not found" error.
Not sure if your problem is related, but worth a try? See if you can add a mime-type "application/json" in the request header of the HttpConnection.
From what I've gathered it seems that when connecting over HTTPS the phone uses an older version of SSL or TLS which has since been deprecated causing some API's to not respond.
I found that if you make an API request over HTTPs with the Opera Mini web browser it works. Giving you the desired response but on closer inspection it seems Opera gets the response for you and gives it back via a different URL. In attempt to furnish these older devices that cannot use a newer version of SSL/TLS to make the secure connection themselves.

Handling parallel REST post requests

I have created my own REST service based on the examples from "Domino Sample REST Service Feature" from 901v00_11.20141217-1000 version of XPages Extension Library.
As far as I understand the design of the library each REST request will be run in its own thread on the server. This approach does not allow to handle parallel POST requests to the same document.
I have not found any examples in XPages Extension Library which would handle post requests as transactions on the server, i.e. which would block the server resource for the whole request processing time and would put put next requests in the queue?
Can anybody point to the source code of the service which would allow to handle parallel requests?
The skeleton for my post request processing function is this
#POST
#Path(PATH_SEPARATOR + MyURL)
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response myPost(
String requestEntity,
#Context final UriInfo uriInfo)
{
LogMgr.traceEntry(this, "myPost");
RestContext.verifyUserContext();
String myJson = ... // Process post
Response response = buildResponse(myJson);
LogMgr.traceExit(this, "myPost", "OK");
return response;
}
And I would like to implement something like this
// Start transaction
String myJson = ... // Process post
// Stop transaction
Is there a way to do it in Java?
I suppose you could use document locking in traditional Notes/Domino context - and synchronized in Java :-)
Have you tried any of these? I cannot see why they should not work.
/John
I agree with John. You can use document locking to prevent simultaneous updates to the same document. You might also want to consider some changes to the definition of your REST API.
First, you imply you are using POST to update an existing document. Usually, POST is used to create a new resource. Consider using PUT instead of POST.
Second, even with document locking, you still might want to check for version conflicts. For example, let's say a client reads version 2 of a document and then attempts to update it. Meanwhile, another client has already updated the document to version 3. Many REST APIs use HTTP ETags to handle such version conflicts.

ASP.NET MVC5 OWIN rejects long URLs

I am creating an ASP.NET MVC5 action method that implements a password reset endpoint and accepts a click-through from an email message containing a token. My implementation uses OWIN middleware and closely resembles the ASP.NET Identity 2.1 samples application.
As per the samples application, the token is generated by UserManager and embedded into a URL that is sent to the user by email:
var token = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
var encoded = HttpServerUtility.UrlTokenEncode(Encoding.UTF8.GetBytes(token));
var uri = new Uri(Url.Link("ResetPasswordRoute", new { id = user.Id, token = encoded }));
The link in the email message targets an MVC endpoint that accepts the token parameter as one of its route segments:
[Route("reset-password/{id}/{token}"]
public async Task<ActionResult> PasswordResetAsync(int id, string token)
{
token = Encoding.UTF8.GetString(HttpServerUtility.UrlTokenDecode(token));
// Implementation here
}
However, requests to this endpoint (using a URL generated in the above manner) fail with Bad Request - Invalid URL.
It appears that this failure occurs because the URL is too long. Specifically, if I truncate the token segment, it connects correctly to the MVC endpoint (although, of course, the token parameter is no longer valid). Specifically, the following truncated URL works ...
http://localhost:53717/account/reset-password/5/QVFBQUFOQ01uZDhCRmRFUmpIb0F3RS9DbCtzQkFBQUFzcko5MEJnYWlrR1RydnVoY2ZwNEpnQUFBQUFDQUFBQUFBQVFaZ0FBQUFFQUFDQUFBQUNVeGZZMzd4OTQ3cE03WWxCakIwRTl4NkVSem1Za2ZUc1JxR2pwYnJSbmJ3QUFBQUFPZ0FBQUFBSUFBQ0FBQUFEcEpnVXFXS0dyM2ZPL2dQcWR1K2x6SkgxN25UVjdMYlE2UCtVRG4rcXBjU0FBQUFE
... but it will fail if one additional character is added ...
http://localhost:53717/account/reset-password/5/QVFBQUFOQ01uZDhCRmRFUmpIb0F3RS9DbCtzQkFBQUFzcko5MEJnYWlrR1RydnVoY2ZwNEpnQUFBQUFDQUFBQUFBQVFaZ0FBQUFFQUFDQUFBQUNVeGZZMzd4OTQ3cE03WWxCakIwRTl4NkVSem1Za2ZUc1JxR2pwYnJSbmJ3QUFBQUFPZ0FBQUFBSUFBQ0FBQUFEcEpnVXFXS0dyM2ZPL2dQcWR1K2x6SkgxN25UVjdMYlE2UCtVRG4rcXBjU0FBQUFEf
I believe that the default IIS configuration setting for maxUrlLength should be compatible with what I am trying to do, but I have also tried explicitly setting it to a larger value, which did not solve the problem.
However, using Fiddler to examine the server response, I can see that the working URL generates a server response with the following header ...
Server: Microsoft-IIS/8.0
... whereas the longer URL is rejected with a response containing the following header ...
Server: Microsoft-HTTPAPI/2.0
This seems to imply that the URL is not being being rejected by IIS, but by a middleware component.
So, I am wondering what that component might be and how I might work around its effect.
Any suggestions please?
Many thanks,
Tim
Note: Although my implementation above Base64 encodes the token before using it in the URL, I have also experimented with the simpler approach used in the sample code, which relies on the URL encoding provided by UrlHelper.RouteUrl. Both techniques suffer from the same issue.
You should not be passing such long values in the application path of the URL as they are limited in length to something like 255 characters.
A slightly better alternative is to use a query string parameter instead:
http://localhost:53717/account/reset-password/5?token=QVFBQUFOQ01uZDhCRmRFUmpIb0F3RS9DbCtzQkFBQUFzcko5MEJnYWlrR1RydnVoY2ZwNEpnQUFBQUFDQUFBQUFBQVFaZ0FBQUFFQUFDQUFBQUNVeGZZMzd4OTQ3cE03WWxCakIwRTl4NkVSem1Za2ZUc1JxR2pwYnJSbmJ3QUFBQUFPZ0FBQUFBSUFBQ0FBQUFEcEpnVXFXS0dyM2ZPL2dQcWR1K2x6SkgxN25UVjdMYlE2UCtVRG4rcXBjU0FBQUFEf
That should be safe for at least 2000 characters (full URL) depending on the browser and IIS settings.
A more secure and scalable approach is to pass a token inside an HTTP header.

Accessing Request, Response, Service and Db Context, etc. in ServiceStack

In my previous project, I use a framework (Agatha RRSL) similar to ServiceStack, in that everything is made of Request, Response and Handler. It also has Interceptors that can attach to handler and you can inject other interfaces to the handler as well. I can use this to open a transaction BeforeHandling, access to both request and response in AfterHandling, create audit, save to database and close transaction if needed.
I try to experiment similar with SerivceStack. But seems with Filters, I can't grab request and response together?
With custom ServiceRunner. When I try to debug OnAfterExecute(...), I can see the name of my request dto in IRequestContext {ServiceStack.ServiceHost.HttpRequestContext}. But just the name, I couldn't figure out how to retrieve the actual request object to work with the response object.
Another thing I haven't figure out is if it's possible to inject the auto wired service interface into it, like a db context or audit service. Maybe this one is too far ahead in the pipeline?
The final thing is, it seems I can only register one custom service runner? With Interceptor, I can drop a bunch of them, and they will wrap around each other.
Any thoughts? Thanks
The RequestContext also contains the HttpRequest and HttpResponse which you can get access with:
var httpReq = RequestContext.Get<IHttpRequest>();
var httpRes = RequestContext.Get<IHttpResponse>();
See the docs on Accessing HTTP Specific features for more info.

Resources