RestSharp behavior change between versions - Token replacement in rest request parameters - restsharp

We're upgrading the version of RestSharp that we use in order to gain support for .NET Core.
Old version is 105.2.3, new version is currently 106.4.0 (but the following applies equally to the latest RestSharp code on GITHub)
Given the following code:
var request = new RestRequest("/webacs/api/v1/data/{reportType}.json?.full=true&collectionTime=ge({collectionTime})&.firstResult={firstResult}");
request.AddParameter("reportType", "HistoricalClientTraffics", ParameterType.UrlSegment);
request.AddParameter("collectionTime", 1497722400000, ParameterType.UrlSegment);
request.AddParameter("firstResult", 0, ParameterType.UrlSegment);
Using RestSharp 105.2.3, when the request is executed (GET) all three UrlSegment parameters cause token substitution to occur and produce a URL like this:
/webacs/api/v1/data/HistoricalClientTraffics.json?.full=true&collectionTime=ge(1497722400000)&.firstResult=0
Using RestSharp 106.4.0 (and also the latest RestSharp source from GITHub) only subsitutions of tokens prior to the '?' occur.
Substitutions beyond the '?' no longer occur and a faulty URL is produced:
/webacs/api/v1/data/HistoricalClientTraffics.json?.full=true&collectionTime=ge(%7BcollectionTime%7D)&.firstResult=%7BfirstResult%7D
(7B and 7D are the ASCII codes for '{' and '}' respectively)
Is this change of behaviour 'by design'?
(It's easy-enough to work around the issue by performing your own token substitutions explicitly)

It is indeed by design. Although technically URL also includes the query, RestSharp is closer to the WebAPI semantics. UrlSegment can be seen as the counterpart of FromRoute and QueryParameter - of FromQuery.
So, when you have the URL http://blah.com/customers/{customerId} and use the following code:
request.AddUrlSerment("customerId", "123");
request.AddQueryParameter("foo", "bar");
it will produce a request to http://blah.com/customers/123?foo=bar.

Related

Karate : How to send query param without url encoding

I'm currently writing Automated REST API tests using Karate dsl and I'm encountering an issue when I try a kind of destructive test. Sending invalid query parameter.
I follow the recommendation from this post Karate: Query Param values are getting encoded who is to use the url only but it seems to not work with query parameter:
Scenario: Destructive testing - Illegal characters in parameters or payload
* def buildURL = 'http://127.0.0.1/identity/client?query={"idClient":{"$eq":9223372036854775807}}'
Given url buildURL
When method GET
Then status 400
error:
java.net.URISyntaxException: Illegal character in query at index 39: http://127.0.0.1/identity/client?query={"idClient":{"$eq":9223372036854775807}}
I have the same kind of test for url path where it works fine, but for query param, this way does not seems to work.
To be clear, my goal is to send query params or at least the character { without url encoding
Any idea to solve that ?
Thanks in advance
karate version : 0.9.6
First, you are trying illegal characters as per the spec, so you may need to manually "URL-encode" the URL - and you already seem to be aware of all this, based on the link in your question. Maybe your server is not compliant with the spec.
Recommend you try upgrading to 1.0 and also refer this open issue: https://github.com/intuit/karate/issues/1561
Anything beyond this will require you to help / contribute code.

Unpassive change in RestSharp 106.6.2

.net Core.
Using RestSharp 106.5.4, this was valid. The Priorities endpoint supports a List<string> priorities as a query parameter.
string server = "http://localhost:11111";
var client = new RestClient(server);
string filter = "?priority=Low&priority=Medium"
var request = new RestRequest($"priorities{filter}", Method.GET);
var response = client.Execute<Priorities>(request);
When I view the response objects ResponseUri property, it has
http://localhost:11111/priorities?priority=Low&priority=Medium
Exactly like I would expect. I upgraded my project to use RestSharp 106.6.2, and the request URI completely changed, and breaks existing code.
With RestSharp 106.6.2, it changes my URI and I get this ResponseUri back
http://localhost:11111/priorities?priority=Low,Medium
This means I now only get one element in my array of string in the request, comma seperated, instead of 2 elements like it did before.
Why was this unpassive change made? This broke our clients because now it only sees one element passed into the list of priorities, and that is "Low,Medium", instead of the two elements in the array as it should. This changes what was passed into the call, and makes the call invalid as Low,Medium is not a value, Low is a value, and Medium is a value.
Is this a defect in restsharps newest version, or was this done on purpose?
I know I can turn and use the parameters objects to do this, but up until the newest restsharp version, I didn't have too and it worked perfectly.

HttpRequestMessage - Decoding 'parameter' - c# net40

I am integrating with a third party API via a PUT request (required). However the URL is not what I consider standard.
https://standard.com/services/U2FsdGVkX18qfVhkTn7JsiXWA8q4vco7vpU%2BmeKqiXKafdKxfJqsq1ELGFOHIilpoR7VXqUcg89yXiabxjjfVXiRmVqGOffsKw%2BKLp5OU6%2FJZaTyn6BYxi%2F10ndtWFLG2KgxRmm%2BxtgTAopUi6m7wWTnSoAlL8qoS%2F3UbiippOw%3D.
Note that the reservation number isn't in the body nor as a parameter, its just a / then the number.
They have encoded the reservation number (requested via another API call). The issue is I'm using HttpRequestMessage, this decodes the %2F to /. Meaning it fails. I have tried double encoding the special characters but this isn't returning a consistent response, sometimes it fails other times it works (using different reservation numbers, only the %2F is double encoded). Is there a way to stop HttpRequestMessage decoding part of the URL?
I have tried encoding/decoding but it always gets stripped out here (unless double encoded:
var path = "https://standard.com/services/U2FsdGVkX18qfVhkTn7JsiXWA8q4vco7vpU%2BmeKqiXKafdKxfJqsq1ELGFOHIilpoR7VXqUcg89yXiabxjjfVXiRmVqGOffsKw%2BKLp5OU6%2FJZaTyn6BYxi%2F10ndtWFLG2KgxRmm%2BxtgTAopUi6m7wWTnSoAlL8qoS%2F3UbiippOw%3D";
var requestMessage = new HttpRequestMessage(HttpMethod.PUT, path);
var requestMessage = (HttpWebRequest)WebRequest.Create(path);
var requestMessage = new HttpRequestMessage(method, new Uri(path));
Update: This was a design decision made by Microsoft:
https://connect.microsoft.com/VisualStudio/feedback/details/511010/erroneous-uri-parsing-for-encoded-reserved-characters-according-to-rfc-3986
The solution from their point of view is to add a setting in the
web.config. But this is a class library and therefore used by more
than one project. I don't want to alter that unless I really have to
This was a design decision made by Microsoft: https://connect.microsoft.com/VisualStudio/feedback/details/511010/erroneous-uri-parsing-for-encoded-reserved-characters-according-to-rfc-3986

How to properly encode special characters in a REST API url

EDIT: The NHTSA docs, as CBroe points out, say to replace an ampersand with an underscore. However, I'm also getting an error with forward slashes (albeit a different one, page not found, because it's decoding the slash), for example the make 'EXISS/SOONER':
http://www.nhtsa.gov/webapi/api/Recalls/vehicle/modelyear/1997/make/EXISS%2FSOONER?format=json
And replacing the ampersand with an underscore no longer results in an error message, but in zero results returned, which should not be the case.
ORIGINAL POST:
I'm trying to download the content from the following URL:
http://www.nhtsa.gov/webapi/api/Recalls/vehicle/modelyear/1997/make/s&s?format=json
And the site returns the following error message:
Server Error in '/' Application.
A potentially dangerous Request.Path value was detected from the client (&).
The problem is the ampersand; a similar request for a different car make works:
http://www.nhtsa.gov/webapi/api/Recalls/vehicle/modelyear/1997/make/toyota?format=json
I have verified from a different endpoint that S&S is a valid make for the API.
Based on stackoverflow answers, I've tried all the following without success:
http://www.nhtsa.gov/webapi/api/Recalls/vehicle/modelyear/1997/make/s%26s?format=json
http://www.nhtsa.gov/webapi/api/Recalls/vehicle/modelyear/1997/make/s%26amp;s?format=json
http://www.nhtsa.gov/webapi/api/Recalls/vehicle/modelyear/1997/make/s%26amp%3Bs?format=json

Problems with Delphi Rest Client talking to C# Rest server

I am writing a REST WCF Service, and have it working for connections from a C# client, but am having issues with connecting via a Delphi 2009 client. The problem I have is specifically with a PUT request, which looks (for the moment) as below. It expects an XML request, containing the document's objects.
[WebInvoke(UriTemplate = "Document/{id}", Method = "PUT", RequestFormat=WebMessageFormat.Xml)]
public void UpdateDocument (string id, Document document)
{
Document doc = document;
// this should update or something!
Console.WriteLine(doc.Id);
}
When I try and call this via my Delphi client (as shown below), I get a 'Bad Request'. Oddly if I send an empty document, the request is received, but obviously has no data.
...
msg := '<?xml version="1.0"?>' +
'<Document>' +
'<Id>123456788888</Id>' +
'</Document>';
XMLDocument1.LoadFromXML(msg);
xmlStream := TMemoryStream.Create;
idHttp1.Request.ContentType := 'application/xml';
XMLDocument1.SaveToStream(xmlStream);
url := 'http://localhost:50435/service1/Document/12345678';
result := idHttp1.Put(url, xmlStream);
ShowMessage (result);
...
Any ideas, as I am a bit lost now!
Thanks
The mapping of the URI to server method is not correct. According to default mapping a PUT request will invoke AcceptDocument method, and a POST request will invoke UpdateDocument method.
http://docwiki.embarcadero.com/RADStudio/en/REST
Also passing a TStream as parameter is also possibility for difficulties. Is it possible for you to use JSON? I am not sure Delphi 2009 has support for JSON though.
Edit:
quote from Delphi documentation:
by default, a prefix of 'update' is assigned to any method invoked
with POST. Similarly, a prefix of 'cancel' is used for DELETE
requests, and a prefix of 'accept' is used for PUT requests. This
prefixing can be avoided by putting quotation marks around the method
name
Above quote applies to Delphi. Maybe also for WCF.
As per my comment above, installing Fiddler made me look at the actual page that the webservice outputs, this helpfully has example XML and json structures. I was missing the namespace for the object, so I guess the WCF end didn't know what to translate, changing the message to the following made it work:
msg := '<?xml version="1.0"?>' +
'<Document xmlns="http://schemas.datacontract.org/2004/07/Contracts.Contracts">' +
'<Id>123456788888</Id>' +
'</Document>';