In one of my recent projects, I was working with RESTCONF on Cisco devices and ran into a bit of an issue. I was trying to make a PUT request and needed to specify the interface name, something like 1/0/1
. But every time I tried, I hit an error. It took me a bit to figure out what was going on, the issue was how special characters in URLs need to be handled. Let's dive into this and see how to get around such problems.
The Problem
When working with RESTCONF, specifically for tasks like fetching or updating interface configurations, I initially expected things to be straightforward. For example, a typical GET request to retrieve information about interfaces would return data in the following structure.
{
"name": "1/0/13"
},
{
"name": "1/0/14",
"switchport-config": {
"switchport": {
"Cisco-IOS-XE-switch:access": {
"vlan": {
"vlan": 10
}
},
"Cisco-IOS-XE-switch:mode": {
"access": {}
}
}
}
}
Here, you can see the interface name 1/0/13
and 1/0/14
along with some configuration details. Based on this, you'd think that if you need to make a POST or PUT request to update an interface, you just specify the interface name as it is, like 1/0/13
. However, this approach led me to an unexpected error. When I tried it, I received the following response.
{
"ietf-restconf:errors": {
"error": [
{
"error-type": "application",
"error-tag": "invalid-value",
"error-message": "uri keypath not found"
}
]
}
}
Continuing with the issue, I decided to use the YANG suite. If you're not familiar, the YANG suite is a handy tool that lets you experiment with API calls right from a user-friendly interface. If you want to learn more about the YANG suite or Restconf in general, please check out my other blog posts below.
While using the YANG suite, I stumbled upon something interesting. I entered 1/1/11
as the interface name, but when I checked the actual PUT request being sent, the name was transformed to 1%2F1%2F11
. This was my "aha" moment.
URL Encoding
URL encoding, also known as percent-encoding, is a method used to encode certain characters in a URL, especially those that could cause ambiguity. In the context of Restconf and network configurations, this becomes particularly relevant.
For standard ASCII characters, like letters and numbers, this isn't an issue. But characters that are not part of standard ASCII, or have special meanings in URLs, need to be converted into a format that can be safely transmitted over the internet. This is where URL encoding steps in.
In URL encoding, these special or non-ASCII characters are replaced with a %
symbol followed by two hexadecimal digits representing their ASCII value. For instance, the forward slash /
– a common character in Cisco interface names like 1/0/13
has a special role in URLs as a separator. In URL encoding, it's represented as %2F
.
So, when I tried to make a PUT request with an interface name 1/0/13
, it needed to be encoded as 1%2F0%2F13
. This encoding ensures that the slash doesn't get misinterpreted as a separator in the URL path, but rather as part of the interface name itself.
Here are the special characters that need encoding ':'
, '/'
, '?'
, '#'
, '['
, ']'
, '@'
, '!'
, '$'
, '&'
, "'"
, '('
, ')'
, '*'
, '+'
, ','
, ';'
, '='
, as well as '%'
itself.
Python Approach
When dealing with Restconf and network configurations programmatically, especially if you have to manage multiple interfaces, it’s not practical to manually encode each interface name. This is where Python can be a real-time-saver.
Python's standard library provides a simple way to handle URL encoding through the urllib.parse
module. Let's look at an example.
import urllib.parse
encoded_interface = urllib.parse.quote('1/0/10', safe='')
print(encoded_interface)
#output
1%2F0%2F10
In this snippet, we're using the quote
function from urllib.parse
. This function is designed to perform URL encoding. We pass in our interface name, 1/0/10
, as an argument. The safe
parameter is set to an empty string, which will encode every character that needs encoding according to the standard URL encoding rules.
The result? Our forward slashes (/
) in the interface name get correctly encoded to %2F
. So, 1/0/10
becomes 1%2F0%2F10
. This encoded string is now safe to use in URL paths for Restconf requests, ensuring that our interface names are correctly interpreted by the network device.