Ah, I solved my little puzzle if anyone is interested: I needed to get a JSON dump of my dictionary before encoding.
data = json.dumps(flow).encode('utf-8') request = urllib.request.Request(url, data) response = urllib.request.urlopen(request) So what is the difference, well *json.dumps* output is encoded as a single element. Using *urllib.parse.urlencode* encodes each element separately. *urllib.parse.urlencode -->* b'dpid=69133577248&cookie=1&cookie_mask=1&table_id=0&idle_timeout=0&hard_timeout=0&priority=0&flags=1&match=%7B%27in_port%27%3A+7%7D&actions=%5B%5D' *json.dumps --> *b'{"dpid": 69133577248, "cookie": 1, "cookie_mask": 1, "table_id": 0, "idle_timeout": 0, "hard_timeout": 0, "priority": 0, "flags": 1, "match": {"in_port": 7}, "actions": []}' Another way I found works is to convert the dictionary to a string (actually that appears to be what json.dumps does) *urllib.parse.urlencode --> * b'dpid=69133577248&cookie=1&cookie_mask=1&table_id=0&idle_timeout=0&hard_timeout=0&priority=0&flags=1&match=%7B%27in_port%27%3A+8%7D&actions=%5B%5D' *json.dumps -->* b'{"dpid": 69133577248, "cookie": 1, "cookie_mask": 1, "table_id": 0, "idle_timeout": 0, "hard_timeout": 0, "priority": 0, "flags": 1, "match": {"in_port": 8}, "actions": []}' *string -->* b"{'dpid': 69133577248, 'cookie': 1, 'cookie_mask': 1, 'table_id': 0, 'idle_timeout': 0, 'hard_timeout': 0, 'priority': 0, 'flags': 1, 'match': {'in_port': 8}, 'actions': []}" as this code option works too. data = str(flow).encode('utf-8') request = urllib.request.Request(url, data) response = urllib.request.urlopen(request) regards, Diarmuid -- *Irish by birth, located in Uganda but Munster by the grace of God.* On Sat, 16 Mar 2019 at 13:45, Diarmuid O Briain <diarm...@obriain.com> wrote: > Hi, > > I have been trying to use the 'ryu.app.ofctl_rest > <https://ryu.readthedocs.io/en/latest/app/ofctl_rest.html#id10>' > interface. Using cURL is fine. Take the following drop rule for example, > works fine. > > curl -X POST -d "{'dpid': '69133577248', 'cookie': 1, 'cookie_mask': 1, > 'table_id': 0, 'idle_timeout': 0, 'hard_timeout': 0, 'priority': 0, > 'flags': 1, 'match': {'in_port': 3}, 'actions': []}" > http://198.8.8.235:8080/stats/flowentry/add > > Now taking the exact same dictionary and URL I try to apply the rul via > python3 urllib. Here is the code snippet. I print out the encoded data to > check it. It fails with a 400 error: > > *flow = {'dpid': '69133577248', 'cookie': 1, 'cookie_mask': 1, 'table_id': > 0, 'idle_timeout': 0, 'hard_timeout': 0, 'priority': 0, 'flags': 1, > 'match': {'in_port': 3}, 'actions': []}* > *url = http://198.8.8.235:8080/stats/flowentry/add > <http://198.8.8.235:8080/stats/flowentry/add>* > > *data = urllib.parse.urlencode(flow).encode('utf-8')* > *print('ENCODED DATA -->', data)* > *with urllib.request.urlopen(url, data) as response:* > * print (response.read().decode('utf-8'))* > > ENCODED DATA --> > b'dpid=69133577248&cookie=1&cookie_mask=1&table_id=0&idle_timeout=0&hard_timeout=0&priority=0&flags=1&match=%7B%27in_port%27%3A+3%7D&actions=%5B%5D' > Traceback (most recent call last): > File "/usr/local/bin/diddly", line 177, in <module> > main() > File "/usr/local/bin/diddly", line 125, in main > diddly_switch.diddly_switch(diddly_args) > File "/usr/local/lib/python3.6/dist-packages/diddly.py", line 4481, in > diddly_switch > diddlySdn._add_flow(self, dict3_['switch_number'], {'match': { > "in_port": p}, 'actions': []}) #>>> [diddly_switch] >>> > File "/usr/local/lib/python3.6/dist-packages/diddly.py", line 6834, in > _add_flow > with urllib.request.urlopen(url_, data) as response: > File "/usr/lib/python3.6/urllib/request.py", line 223, in urlopen > return opener.open(url, data, timeout) > File "/usr/lib/python3.6/urllib/request.py", line 532, in open > response = meth(req, response) > File "/usr/lib/python3.6/urllib/request.py", line 642, in http_response > 'http', request, response, code, msg, hdrs) > File "/usr/lib/python3.6/urllib/request.py", line 570, in error > return self._call_chain(*args) > File "/usr/lib/python3.6/urllib/request.py", line 504, in _call_chain > result = func(*args) > File "/usr/lib/python3.6/urllib/request.py", line 650, in > http_error_default > raise HTTPError(req.full_url, code, msg, hdrs, fp) > urllib.error.HTTPError: HTTP Error 400: Bad Request > > -- > > *Irish by birth, located in Uganda but Munster by the grace of God.* > > >
_______________________________________________ Ryu-devel mailing list Ryu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ryu-devel