parsing parameters

52 views
Skip to first unread message

Christopher Hobbs

unread,
Jul 30, 2012, 12:33:44 PM7/30/12
to golang...@googlegroups.com
Incoming ignorant question.  I've been browsing the docs, but I may not be looking in the right place.

How do you parse parameters with goweb?  I know about mapping with PathParams, but I'm having a little trouble grabbing anything beyond static parameters.  As an example, if I have the following:

type MyController struct {}
func (cr *MyController) Create(cx *goweb.Context) {  
  // do something useful with any parameters here
}

And I map that to "/api" with goweb.MapRest, how would I parse 'foo' in POST http://localhost/api?foo=bar

Christopher Hobbs

unread,
Jul 30, 2012, 1:39:49 PM7/30/12
to golang...@googlegroups.com
It looks like I can actually parse RawQuery, but that seems a little hackish.  Is there a better way?

Tyler Bunnell

unread,
Aug 1, 2012, 4:50:28 PM8/1/12
to golang...@googlegroups.com
I've just pushed a new experimental branch to the repository called "argparsing".

This branch gives you a new object in the context object called "DynamicPathParams". This object will be populated with the key/value pair for all the dynamic arguments after the ? in the path.

It passes basic tests at this point, but has not undergone any stressful usage. Also, as this is an experimental branch, the name of the field may change at some point in the future.

Please do feel free to give it a shot and let us know how it works for you!

-Tyler

Christopher Hobbs

unread,
Aug 1, 2012, 9:58:50 PM8/1/12
to golang...@googlegroups.com
That's great!  I'll check the branch out.
Message has been deleted

matryer

unread,
Aug 2, 2012, 5:31:38 PM8/2/12
to golang...@googlegroups.com
Tyler,

I wonder if a simpler solution might be better here?

To get Query parameters currently, you can do this:

type MyController struct {}
func (cr *MyController) Create(cx *goweb.Context) {  
  cx.Request.FormValue("foo")
}

That's not too hard, is it?  But, we could make it even easier by providing a 'FormValue' method on the Context... so you could do this:

type MyController struct {}
func (cr *MyController) Create(cx *goweb.Context) {  
  cx.FormValue("foo")
}

Does this do everything the 'dynamic path params' work did?  Or did your code do something extra?

Mat

Tyler

unread,
Aug 2, 2012, 5:59:26 PM8/2/12
to golang...@googlegroups.com, golang...@googlegroups.com
I had no idea that was possible so I did it all manually. All that it does is provide a map for the form values. The convenience method would most likely be faster and better overall. 

I suppose the only thing that it provides which your method does not would be the ability to iterate the collection


Sent from my iPhone

On Aug 2, 2012, at 3:30 PM, matryer <mat...@mac.com> wrote:

Tyler,

I wonder if a simpler solution might be better here?

To get Query parameters currently, you can do this:

type MyController struct {}
func (cr *MyController) Create(cx *goweb.Context) {  
  cs.Request.FormValue("foo")
}

That's not too hard, is it?  But, we could make it even easier by providing a 'FormValue' method on the Context... so you could do this:

type MyController struct {}
func (cr *MyController) Create(cx *goweb.Context) {  
  cs.FormValue("foo")
}

Does this do everything the 'dynamic path params' work did?  Or did your code do something extra?

Mat


On Wednesday, August 1, 2012 2:50:28 PM UTC-6, Tyler Bunnell wrote:
I've just pushed a new experimental branch to the repository called "argparsing".

This branch gives you a new object in the context object called "DynamicPathParams". This object will be populated with the key/value pair for all the dynamic arguments after the ? in the path.

It passes basic tests at this point, but has not undergone any stressful usage. Also, as this is an experimental branch, the name of the field may change at some point in the future.

Please do feel free to give it a shot and let us know how it works for you!

-Tyler

Tyler Bunnell

unread,
Aug 2, 2012, 9:05:18 PM8/2/12
to golang...@googlegroups.com
Mat,

I've found a new way of doing it that is far more efficient and reliable while also maintaining the map for iterating.

However, I'm wondering if being able to iterate over the query parameters is a plus? Does it really matter that much? Can anyone see a use for this?

Also, it seems in some of the tests you are passing query parameters such as context, callback, api, etc. These will all be exposed in the map of the parameters. Is that something we should worry about? Does it matter? Should we filter them out?

-Tyler

Christopher Hobbs

unread,
Aug 3, 2012, 12:39:02 AM8/3/12
to golang...@googlegroups.com
I think iterating over the parameters would be useful for handling bad
input, that was my initial issue. In fact, I found out about
FormValues when I was working on uploading files (see
https://groups.google.com/forum/?fromgroups#!topic/golang-goweb/GCCMSvOODbM).
--
Christopher M. Hobbs
http://altbit.org

Tyler Bunnell

unread,
Aug 5, 2012, 6:59:37 PM8/5/12
to golang...@googlegroups.com
I just pushed an update to the argparsing branch that has a more efficient and reliable way of creating the QueryParams (previously DynamicPathParams).

Take a look and let me know what you think. I feel like this is a good balance between the .FormValues approach and my old approach.

If iteration is something that we determine can be scrapped entirely, we can remove this approach and simply add helper methods. However, this approach seems a bit more clear/consistent to me, as it is similar to the PathParams.

Also, Mat, do you think we should filter out the query parameters that are used by the API, such as always200 and callback, etc?

Thoughts?

-Tyler

Christopher Hobbs

unread,
Aug 10, 2012, 2:34:54 PM8/10/12
to golang...@googlegroups.com
Just took the branch for a test drive and everything looks solid to me.  Do you plan to merge this into master?

Tyler Bunnell

unread,
Aug 10, 2012, 2:36:43 PM8/10/12
to golang...@googlegroups.com
Wonderful! Glad to hear it has worked for you in a more realistic environment (rather than just a test module).

We will probably merge this in to master at some point, but I need to make sure everything is cool with Mat before doing anything drastic. ;)

Thanks for testing it!

-Tyler

matryer

unread,
Aug 13, 2012, 5:08:23 PM8/13/12
to golang...@googlegroups.com
Hey Tyler,

I have some questions:
  • What did we agree on this approach vs using FormValue() on http.Request object?
  • Should we hide QueryParams behind a function so it does the work only when it needs to?
  • Should we support multiple values (it seems to pick only the first value currently), which would mean the value could even be string or []string.  But perhaps we could just standardise on []string and let the users worry about their API.
Mat

Tyler

unread,
Aug 13, 2012, 5:19:14 PM8/13/12
to golang...@googlegroups.com
Response inline:

Sent from my iPhone

On Aug 13, 2012, at 3:08 PM, matryer <mat...@mac.com> wrote:

Hey Tyler,

I have some questions:
  • What did we agree on this approach vs using FormValue() on http.Request object?
We never came to a final decision on this. I like the params approach as it is similar to the path params. Consistent. However, we could nix this entirely. It's all an experiment. :-)

  • Should we hide QueryParams behind a function so it does the work only when it needs to?
That sounds like a great idea, actually. 

  • Should we support multiple values (it seems to pick only the first value currently), which would mean the value could even be string or []string.  But perhaps we could just standardise on []string and let the users worry about their API.
Correct, it picks the first currently. I couldn't find any examples of multiple values, however. Could you provide one?

We certainly could just return the array and let the use worry about it. Or we could try to be clever and return an array when there are multiple and a variable when there is single. It seems like it would be a pain to always work with array notation when working with a single value. 

Thoughts?

-Tyler

Christopher M. Hobbs

unread,
Aug 13, 2012, 10:54:36 PM8/13/12
to golang...@googlegroups.com
I don't think there's anything wrong with "dealing" with array
notation for a single parameter. I believe it's more flexible that
way.

--
Christopher M. Hobbs
http://altbit.org

matryer

unread,
Aug 14, 2012, 10:13:46 AM8/14/12
to golang...@googlegroups.com
Tyler,

Thanks for your response.

Here's an example of multiple values:

   /favourite-animals?animal=dog&animal=cat&animal=monkey

So 'animal' would be an array of three values ["dog", "cat", "monkey].

Regarding the idea of returning an array when it's an array and a single value when there's only one... the problem is this causes an inconsistent API.  E.g. you could code assuming one animal, which would cause your code to actually crash if somebody provided many.  Consistency over clever code wins here I think.

Do you want to have a go at implementing the 'caching' bit for QueryParams?  Usually it's as simple as:
  1. make the QueryParams private (by lower-casing the Q), this becomes the internal storage value
  2. write a test to assert that the queryParams value is nil (or empty)
  3. add a function called QueryParams
  4. write a test proving that a) QueryParams() returns something, and b) that it's the same thing stored in queryParams
  5. NOTE: You can access private internal stuff when writing tests because the tests are within the same package
  6. In cases of maps, nil doesn't necessarily make sense, so if that doesn't work, you might need to add a 'bool' to indicate whether the initialisation work has bee done or not.

Mat

Tyler Bunnell

unread,
Aug 14, 2012, 10:21:15 AM8/14/12
to golang...@googlegroups.com
On Aug 14, 2012, at 8:13 AM, matryer <mat...@mac.com> wrote:

> Here's an example of multiple values:
>
> /favourite-animals?animal=dog&animal=cat&animal=monkey

Oh duh! So simple. I've never actually used that myself. Makes total sense though. We'll definitely go with having it return <string,[]string>.

> Consistency over clever code wins here I think.

Agreed.

> Do you want to have a go at implementing the 'caching' bit for QueryParams? Usually it's as simple as:
> • make the QueryParams private (by lower-casing the Q), this becomes the internal storage value
> • write a test to assert that the queryParams value is nil (or empty)
> • add a function called QueryParams
> • write a test proving that a) QueryParams() returns something, and b) that it's the same thing stored in queryParams
> • NOTE: You can access private internal stuff when writing tests because the tests are within the same package
> • In cases of maps, nil doesn't necessarily make sense, so if that doesn't work, you might need to add a 'bool' to indicate whether the initialisation work has bee done or not.

Absolutely! I'll try to bang that out today. :)

Tyler Bunnell

unread,
Aug 14, 2012, 10:55:00 AM8/14/12
to golang...@googlegroups.com
Please check the argparsing branch to see the update QueryParams.

Also, Mat, do you think we should bother filtering out various parameters that are API specific, such as always200, callback and context? Having those appear in the QueryParams map may be confusing.

On Aug 14, 2012, at 8:13 AM, matryer <mat...@mac.com> wrote:

matryer

unread,
Aug 16, 2012, 4:19:24 PM8/16/12
to golang...@googlegroups.com
That's an interesting question, I guess we can filter them out and if people really need more control they can access the Query directly via the http.Request object.

Tyler Bunnell

unread,
Aug 16, 2012, 4:20:18 PM8/16/12
to golang...@googlegroups.com
Sounds like a plan. Let me know what you think about the latest changes and I'll work on filtering the API specific query parameters.

Tyler Bunnell

unread,
Aug 17, 2012, 1:28:50 PM8/17/12
to golang...@googlegroups.com
I've implemented query filtering and pushed the new code to the argparsing branch.

On Aug 16, 2012, at 2:19 PM, matryer <mat...@mac.com> wrote:

Reply all
Reply to author
Forward
0 new messages