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 <[email protected]>
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel