Question
Daniel Kutac · Jun 1, 2016

Passing a parameter with slashes to the REST call

I need to pass a parameter string that contains slashes to a REST call.

I tried URL encoding, or making URL map to accept query parameter instead of path parameter but apparently we only allow for path parameters.

I can come with several workarounds, but these involve some transformation at client and then on server, but I'd prefer a direct support.

Q1: is there any Cache specific trick to pass slashes in path parameters

Q2: are we going to support query parameters in REST?

something like this would help: 

<Route Url="/test?var=:var" Method="GET" Call="Test" Cors="true"/>

 Dan Kutac

00
0 0 18 30,591
Log in or sign up to continue

I have never actually tried to pass slashes as parameters, but I would guess that it should work if you encode them. I am aware that some systems drop these requests, because it is easy to inject malicious code this way.

Are you receiving a 404 and use Apache? If so, you may have to enable  the AllowEncodedSlashes directive:

http://httpd.apache.org/docs/current/mod/core.html#allowencodedslashes

Cool!

Thanks Stefan, yes I used Apache that comes with Cache. Putting directive you suggested solved my issue.

Dan

PS: use case = pass pivot name into a rest service, I tend to use slashes to organize my DeepSee stuff into 'folders'

Q1:

1. JS client sends URL encoded string automatically or almost automatically (most frameworks do URL encoding for any URL)

2. In your broker override OnPreDispatch method and unescape pURL with:

set pURL = $ZCONVERT($ZCONVERT(pURL,"I","URL") ,"I","UTF8")

Q2: It is against core REST architecture principles, so I hope not.

Q2: It is against core REST architecture principles, so I hope not.

That is not entirely true. Filters and action descriptions are commonly exposed as URL parameters as they serve to either specify an action or limit the working set. But you are still operating on the same resource identity.

What you can observe is that REST is just a best practice leveraging HTML. You will find any possible implementation of REST interfaces out there, some are true to the original spirit, some are not.

Anyway, you can fight endless wars about REST  interfaces, but one thing is for sure: URL parameters are commonly used for REST interfaces.

To answer the original question: I don't see a need to add URL parameters to the URL map. They would only add value if we added them as method arguments, but I think that would be very confusing as path variables are passed as arguments at the moment.

You can use the %request.Data property to retrieve the URL parameters.

 

I have not been able use the %request.Data property with URL parameters in a GET.  Is this now available? The testing I did last week (Just using an external REST tool and passing parameters in different formats) didn't allow me to get any URL body parameters in the %request.Data property. They weren't defined.

Hi Eduard,

I am running in the same issue as Dan and trying out your solution in assumption that there is no other better way of handling this. Overriding OnPreDispatch doesn't seem to work for me. My URL seems decoded by then.

E.g. my API URL is

http://localhost:52773/mapi/admin/v1/patients/{patientReference} where patientReference contains a slash so client call would be something like

http://localhost:52773/mapi/admin/v1/patients/ipm%2F3245678

In my OnPreDisptach pUrl is  already decoded

v1/patients/ipm/3245678 

hence your solution doesn't seem to work. Am I missing something? Is there any  other way of handling this?

Thanks,

Utsavi

Are you using Apache2 (private web server is Apache2)?

What's your AllowEncodedSlashes value?

You need both AllowEncodedSlashes = true and encoding the parameter for this to work.

Thanks for the quick response Eduard. Its just the default Apache sever that comes with IRIS. How do I check/change AllowEncodedSlashes  setting?

Change httpd.conf in <iris>\httpd\conf and restart iris (or at least the web server).

What the issue you faced?

Class User.Rest Extends %CSP.REST
{

XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
<Route Url="/:resource/(.*)" Method="GET" Call="GetResource" Cors="true"/>
<Route Url="/ping" Method="GET" Call="Ping" Cors="true"/>
</Routes>
}

ClassMethod Ping() As %String
{
  Write {"pong": true}.%ToJSON()
  Return $$$OK
}

ClassMethod GetResource(pResource As %String, pId As %String) As %Status
{
  Write {"resource": (pResource), "id": (pId)}.%ToJSON()
  Return $$$OK
}

}

With this REST class, I can do queries like this http://localhost:52773/rest/patient/test/123/456, with no issues it returns {"resource":"patient","id":"test/123/456"}

Thanks Dmitry:) that actually works for me too if i change my route from /patients/{patientRef} to /patients/(.*) in the dispatch class. 

My only problem now is that my api specification says the route is /patients/{patientRef} and because we are using the iris api/mgmnt api to auto generate rest classes based on Swagger specification, my dispatch class is auto generated based on .spec class. My .disp class also gets overwritten everytime my .spec class is recompiled.  Any ideas on how to get around this?

Many thanks, 

Utsavi

I would not recommend using it this way, due to many limitations and issues in it. Just make it on your own.

Would it be possible to implement a POST instead and pass the information containing the / characters as part of the body rather than the URL?

Yes, it is, but I am not sure if it is applicable to Dan's use case. The biggest technical difference is that GETs are cached by clients, while POSTs must not be cached.

Stefan's initial answer is the best for me. Everything else is just too much work.

Bumping this up in case anyone has any other solutions.

Thanks Dmitry:) that actually works for me too if i change my route from /patients/{patientRef} to /patients/(.*) in the dispatch class. 

My only problem now is that my api specification says the route is /patients/{patientRef} and because we are using the iris api/mgmnt api to auto generate rest classes based on Swagger specification, my dispatch class is auto generated based on .spec class. My .disp class also gets overwritten everytime my .spec class is recompiled.  Any ideas on how to get around this?

Many thanks, 

Utsavi