Wednesday, 17 March 2010

Python http PUT request

I have a CherryPy service which accepts 'PUT' requests with a named payload parameter (it's name is , surprisingly, 'payload'). From cURL, this is easy to specify with the -F option, but I couldn't find anywhere how to do this with Python. I discovered something a bit odd, which seems to be that the payload needs to be specified twice:

import urllib, httplib
import time, calendar
import base64

if __name__=='__main__':
timenow=time.gmtime()
t=time.asctime(timenow)
iov1=str(calendar.timegm(timenow))+'000000000'
iov2=str(calendar.timegm(timenow) + 1) +'000000000'
p=''+t+''
px=urllib.quote_plus(p)
pe=urllib.urlencode({"payload":p})
urlbase='putserver.cern.ch:8081'
testPut='DEVDB10/ATLAS_SCT_COMMCOND_DEV/PUTS200/TEST/PUT/Multi/timespan/'+iov1+''+iov2+"?payload="+px
test='/cooldb'
testMerge='/cooldb/merge'
print px
print urlbase
authHeader={"Authorization": "Basic "+base64.encodestring('name:pwd'), "Content-Length":str(len(px))}
#payload=px
h=httplib.HTTPConnection(urlbase)
h.request('PUT',testPut,px,authHeader)
r=h.getresponse()
print r.status, r.reason
print r.read()
h.close()

Wednesday, 3 March 2010

I wanted an iomanipulator to escape XML

...and so began a steep learning curve. I had some strings to insert into XML being output on the cout stream, and ideally I would simply like to do something like this:
string myXml("xml&<>");
cout<<escapexml<<myXml;

..and the output should be 'escaped'.
Of course I could have made a function and simply transformed one string into another, but I was also keen to learn about the iostream framework. Here are a few ways which iterate towards the final goal
1. 'Adapt' the string
Custom inserters can be made for a given class, so by wrapping the string in a class, I cold simply make an inserter for that class:
Here is the header:

class Wrapper{

std::string &m_data;

public:

typedef std::string::value_type value_type;Font size

Wrapper(std::string & data):m_data(data){ }

std::string &str(){

return m_data;

}

};


std::ostream &

operator << (std::ostream & os, Wrapper & s);


...and the definition for that inserter:

std::ostream &

operator<< (std::ostream & os, Wrapper & s){

XmlEscape x(os);

for_each(s.str().begin(),s.str().end(),x);

return os;

}


where XmlEscape is a functor:


class XmlEscape{

static const char * m_chars;

static const char * m_replacements[];

static const unsigned int m_nchars=5;

std::ostream & m_os;

public:

XmlEscape(std::ostream & os);

void operator()(char c);

std::ostream & ostream();

};


with implementation:


const char * XmlEscape::m_chars ="&\'\"><";

const char * XmlEscape::m_replacements[]={"&amp;", "&apos;", "&quot;", "&gt;", "&lt;"};


XmlEscape::XmlEscape(std::ostream & os):m_os(os){

//nop

}


void

XmlEscape::operator()(char c){

unsigned int i(m_nchars);

while(i--){

if (c==m_chars[i]) {

m_os<<m_replacements[i];

return;

}

}

m_os<<c;

}

2. Adapt the stream