Tag: url

Converting nested hash into HTTP url params hash version in Ruby

We cannot send nested hash as a param in HTTP requests. For example, when we would like to send something like this:

{:key => "value", :nested => {:nest => "value"}}

It would be (or should be) mapped like this:

/url/?key=value&nested=%7B%3Anest%3D%3E%5C%22value%5C%22%7D

Doesn't look to good ;) However there is a simple way to convert a nested hash into a params acceptable form. We can convert it to a form, that can be mapped into params like this:

/url/?key=value&nested[nest]=value

Here is method to convert any nested hash to a "one level" equivalent:

  module HashConverter

    def self.encode(value, key = nil, out_hash = {})
      case value
      when Hash  then 
        value.each { |k,v| encode(v, append_key(key,k), out_hash) }
        out_hash
      when Array then 
        value.each { |v| encode(v, "#{key}[]", out_hash) }
        out_hash
      when nil   then ''
      else
        out_hash[key] = value
        out_hash
      end
    end

    private

    def self.append_key(root_key, key)
      root_key.nil? ? :"#{key}" : :"#{root_key}[#{key.to_s}]"
    end

  end

And usage example:

hash = {:level0 => 'value', :nested => {:nest1 => "val1", :nest2 => "val2"}}
HashConverter.encode(hash)
#=> {:level0=>"value", :"nested[nest1]"=>"val1", :"nested[nest2]"=>"val2"}

This form can be easily mapped into a HTTP url params

Relative and absolute urls expanding in Python

Today I've got a quite interesting piece of code, used to expand urls (join them when they are in parts). For example:

expand_url('http://www.test.com/', '/me') 
  => http://www.test.com/me
expand_url('http://www.test.com/abc', 'test') 
  => http://www.test.com/abc/test

Code was quite "crazy" (not mine):

import re
from urlparse import urlparse, urljoin, urlunparse

def expand_url(home, url):
    if re.match(r"^\w+\://", url):
        return url
    else:
        parts = home.split('/')
        if len(parts) > 2:
            if re.match(r"^/", url):
                return "%s//%s%s" % (parts[0], parts[2], url)
            else:
                url = url.split('/')
                if url[0] == '.':
                    del(url[0])
                proto = parts.pop(0)
                return "%s//%s" % (proto, "/".join(parts[1:-1] + url))
        else:
            return False

and it had one big disadvantage. When expanding urls with relative parts it didn't include hierarchies levels, so the output urls looked like this:

expand_url('http://www.test.com/', './../me')
  => http://www.test.com/./../me
expand_url('http://www.test.com/abc', './../../test') 
  => http://www.test.com/abc/./../../test

Lil bit messy I think. After googling I've found a nice and smaller expanding method (which works like a charm):

import posixpath
from urlparse import urlparse, urljoin, urlunparse

def expand_url(home, url):
    join = urljoin(home,url)
    url2 = urlparse(join)
    path = posixpath.normpath(url2[2])

    return urlunparse(
        (url2.scheme,url2.netloc,path,url2.params,url2.query,url2.fragment)
        )
expand_url('http://www.test.com/', './../me') 
  => http://www.test.com/me
expand_url('http://www.test.com/abc', './../../test') 
  => http://www.test.com/test

Copyright © 2024 Closer to Code

Theme by Anders NorenUp ↑