(Migrated) obtaining payload from get or url params


#1

(This message has been automatically imported from the retired mailing list)

hi all,

i’m evaluating zato and have become stuck at this topic. how can i access p=
ayloads passed in as get parameters or url variables? as examples:

http://some.url/something/search?a=3Db&c=3Dd (a and c are the search parame=
ters the service needs)
http://some.url/something/1234 (1234 is an identifier needed by the service=
and as such a variable component of the url)

get parameters seem to vanish altogether (request.raw_string is blank) and =
i haven’t been able to find an example of how to do the latter with Zato :confused:

thanks
ozgur


#2

On 07/24/2013 05:12 AM, Ozgur Susoy wrote:

Hi Ozgur, thanks for your interest!

how can i
access payloads passed in as get parameters or url variables? as examples:

http://some.url/something/search?a=b&c=d (a and c are the search
parameters the service needs)
http://some.url/something/1234 (1234 is an identifier needed by the
service and as such a variable component of the url)

Query string is part of the HTTP WSGI environment and can accessed as below

stdlib

from urlparse import parse_qs

Zato

from zato.server.service import Service

class MyService(Service):
def handle(self):
qs = parse_qs(self.wsgi_environ[‘QUERY_STRING’])
self.logger.info(qs[‘foo’])

If you’re wondering why it’s not directly accessed through self.request,
this is simply because I didn’t have time to add GET to the
’data_format’ select list when creating a new HTTP channel like here

https://zato.io/docs/web-admin/channels/plain-http.html

I mean to add it along with CSV in addition to already JSON and XML and
then it will be possible to access it through

self.request.payload.foo # read from ?foo=baz

I just don’t feel conceptually something like self.request.qs is the
right place - not everything is HTTP. WSGI on the other hand is a
well-established means to convey such information hence maybe in
addition to what I wrote above (HTTP channel with GET data_format) the
same information could be put into

self.wsgi_environ[‘zato.http.qs’].foo # read from ?foo=baz

Would do you think?

In that way, if your service operates on GET parameters /only/ you’d set
its data_format to GET.

If on the other hand the service receives both, say, JSON in POST
payload along with some additional GET parameters, the latter would be
accessible through self.wsgi_environ[‘zato.http.qs’].

Unless of course you always receive both POST and GET parameters so in
that situation the GUI can be given a ‘Merge GET’ checkbox and they
could all be merged into self.request.payload, sure, why not.

I’m just not sure what is the most common scenario you’re dealing with?
Me, I’ve always had either POST or GET but not both though I understand
others may have different approaches.

get parameters seem to vanish altogether (request.raw_string is blank)
and i haven’t been able to find an example of how to do the latter with
Zato :confused:

I’m travelling today and won’t be able to do it but it sure needs to be
added to usage examples at

https://zato.io/docs/progguide/examples/http.html

you’re absolutely right!


#3

On 07/24/2013 05:12 AM, Ozgur Susoy wrote:

Hi Ozgur, thanks for your interest!

how can i
access payloads passed in as get parameters or url variables? as examples:

http://some.url/something/search?a=b&c=d (a and c are the search
parameters the service needs)
http://some.url/something/1234 (1234 is an identifier needed by the
service and as such a variable component of the url)

Query string is part of the HTTP WSGI environment and can accessed as below

stdlib

from urlparse import parse_qs

Zato

from zato.server.service import Service

class MyService(Service):
def handle(self):
qs = parse_qs(self.wsgi_environ[‘QUERY_STRING’])
self.logger.info(qs[‘foo’])

If you’re wondering why it’s not directly accessed through self.request,
this is simply because I didn’t have time to add GET to the
’data_format’ select list when creating a new HTTP channel like here

https://zato.io/docs/web-admin/channels/plain-http.html

I mean to add it along with CSV in addition to already JSON and XML and
then it will be possible to access it through

self.request.payload.foo # read from ?foo=baz

I just don’t feel conceptually something like self.request.qs is the
right place - not everything is HTTP. WSGI on the other hand is a
well-established means to convey such information hence maybe in
addition to what I wrote above (HTTP channel with GET data_format) the
same information could be put into

self.wsgi_environ[‘zato.http.qs’].foo # read from ?foo=baz

Would do you think?

In that way, if your service operates on GET parameters /only/ you’d set
its data_format to GET.

If on the other hand the service receives both, say, JSON in POST
payload along with some additional GET parameters, the latter would be
accessible through self.wsgi_environ[‘zato.http.qs’].

Unless of course you always receive both POST and GET parameters so in
that situation the GUI can be given a ‘Merge GET’ checkbox and they
could all be merged into self.request.payload, sure, why not.

I’m just not sure what is the most common scenario you’re dealing with?
Me, I’ve always had either POST or GET but not both though I understand
others may have different approaches.

get parameters seem to vanish altogether (request.raw_string is blank)
and i haven’t been able to find an example of how to do the latter with
Zato :confused:

I’m travelling today and won’t be able to do it but it sure needs to be
added to usage examples at

https://zato.io/docs/progguide/examples/http.html

you’re absolutely right!


#4

What would be the way to parse parameters from the URL path, should we not be using SimpleIO to implement a service?

Getting them from the query string comes down to using:

qs = parse_qs(self.wsgi_environ[‘QUERY_STRING’])

But what about when using something like GET /app/users/{id} or DELETE /app/users/{id}/roles/{id}? How to parse those parameters when not using SimpleIO?

I take it we would have to parse self.wsgi_environ[‘PATH_INFO’] or parse the self.request.payload variable. Any library to do so? Would we have to “know” the path previously configured in the channel?

Thanks.


#5

The way to access HTTP metadata is as follows:

class MyService(Service):
    class SimpleIO:
        input_optional = ('id', 'name')

    def handle(self):
        # This is from SimpleIO
        self.logger.info('id=%s', self.request.input.id)
        self.logger.info('name=%s', self.request.input.name)

        # This is from metadata
        self.logger.info('phone=%s', self.request.http.GET['phone'])
        self.logger.info('HTTP method=%s', self.request.http.method)

A sample curl invocation would be:

$ curl localhost:11223/zzz?phone=+199988777 -d '{"id":"123", "name":"NAME"}'

As for accessing path parameters, you are right that it is a good idea to add it to self.request.http.

Can you please open a combined GitHub ticket for it all? That is.

  • Adding an output_repeated usage example
  • Adding self.request.http.path and a usage example for it
  • Adding docs for self.request.http

Thank you.


#6

Thanks for the reply, @dsuch.

Just to clarify before opening the ticket on Github, I am not talking about getting the parameter values in the path when using SimpleIO, as it already does the job, but when not using SimpleIO. Okay?

P.S. The reason behind my request is so that we can use multiple handle_VERB in a single service class and have access to the parameters in the URL path without using SimpleIO, as there is no SimpleIO_VERB interface.


#7

I am not talking about getting the parameter values in the path when using SimpleIO, as it already does the job, but when not using SimpleIO. Okay?

Yes, this is is understood. The case with path parameters with SimpleIO is already handled, it is only about getting a handle to the parameters that are outside of SIO.

That information is already available internally so it is mostly about exposing it to a user-level attribute.


#8

@dsuch, I have added two tickets on GitHub, as requested. Please le me know if you need anything else and please feel free to take anything from the tests I am doing in my online repository at Bitbucket.