Cisco Restconf - URL Encoding

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.

How to Install Cisco YANG Suite? (Example with C9300)
In today’s post, we’re diving into Cisco YANG Suite, a tool that makes using netconf/restconf a breeze. If you want to easily configure and manage your network
Cisco Restconf Example
In today’s blog post, we’re going to explore how to interact with a Cisco 9300 switch using RESTCONF and Python. We’ll focus on two main tasks, retrieving VLAN information and then configuring new VLANs.

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.

Further reading

https://docs.python.org/3/library/urllib.parse.html