DEV Community

PyBash
PyBash

Posted on • Originally published at pybash.hashnode.dev on

Making A Custom Protocol Handler and URI Scheme! - Part 1

Introduction

In this miniseries, I will be telling you, how to make a custom URI scheme or URI and a Protocol Handler for that URI. An example of one such URI is vscode:///! You might have seen this when you try to sign in to GitHub using VS Code, right? But we are not going to be making exactly this, slightly different! The Finished Product is given below!

The Finished Product?

Well, so what are we actually, going to make? Well, we will be making a protocol python:// that will enable us to execute any python script on our computer right from our browser! Isn't that cool? And maybe in the future, we could make it so that it could run any python file on the internet! A video of the finished product is given below! Sorry for the bad quality, I had to reduce it for Hashnode to fit inside the article!

So, what are we making today?

Today we are going to be making the basic handler in Python using urllib! I will be using Python 3, but this can easily be translated into Python 2 using the urllib2 module! So, let's get started!

Prerequisites

  1. Python
  2. urllib module - included in the standard library
  3. StringIO - included in the standard library

Actual Code!

Well, in this post we will just be making the basic handler, the script execution will be in the next post!

Imports

import urllib.request as urlreq
from io import StringIO as strio

Enter fullscreen mode Exit fullscreen mode

We need a urllib.request for parsing the protocol address and creating the handler! We will not be needing StringIO, from the next post, it's just for this post!

The Handler

Alright, so the imports are done, now let's move on to the actual handler! This will use some very basic Object-Oriented Programming(OOP), so even if you are not familiar with it there will be no problem, but if you are familiar, it will help!

class PyProtoHandler(urlreq.BaseHandler):
    def python_open(self, req):
        fullUrl = req.get_full_url()
        return strio(fileUrl)

Enter fullscreen mode Exit fullscreen mode

So, in the above code, we made a class named PyProtoHandler which inherits from urllib.request.BaseHandler. Inside this class we define a new function named python_open, which takes in 1 parameter req, but here comes the crucial bit, This function has to be named in a specific way, i.e., {the protocol name}_open. If you for example define the function as myproto_open and your actual protocol is protomy, then it is just going to give an error, so keep this in mind!

Then, we store the full URL returned by req.get_full_url() in fullUrl. And finally return fullUrl wrapped in StringIO.

Installing the Handler

Alright, so the handler is made, let's install and build it. This step is really simple, we just need to call 2 built-in functions of urllib!

opener = urlreq.build_opener(PyProtoHandler())
urlreq.install_opener(opener)

Enter fullscreen mode Exit fullscreen mode

So, we build the opener using urlreq.build_opener(PyProtoHandler) and store the returned result or output in the variable opener. Next, we install the opener using urlreq.install_opener(opener). And we are done! viola! So, let's test it!

Testing the Handler

We will be using another line of code with this file to test it!

print(urlreq.urlopen("python://something/random/file.txt").read())

Enter fullscreen mode Exit fullscreen mode

Now to test, we have to run the file from our Terminal or Bash or Command Prompt, whatever you wish! You might have to use python or python3 depending on your system.

$ python protoHandler.py
python://something/random/file.txt

Enter fullscreen mode Exit fullscreen mode

Running the file once again with changes to the code:

print(urlreq.urlopen("python://hashnode/non-existing/dir/non/existing/file.py").read())

Enter fullscreen mode Exit fullscreen mode

And, output:

$ python protoHandler.py
python://hashnode/non-existing/dir/non/existing/file.py

Enter fullscreen mode Exit fullscreen mode

The End Get the file path!?

I didn't think I would include this here, but finally, I did! so, enjoy, everyone!

Well, Now that, we can get the whole protocol, we can now extract the path to the file.

class PyProtoHandler(urlreq.BaseHandler):
    def python_open(self, req):
        fullUrl = req.get_full_url()
        filePath = "".join(fullUrl.split("://")[1:])
        return filePath

Enter fullscreen mode Exit fullscreen mode

So, as you can see, I have just added a line to the python_open function. Which splits the protocol into a list, where, the 1st element is the protocol("python") and the second element is the file path. And we wrap that up in "".join() to convert the path into a string and join all the elements from and after element at the index 1 with "" as the separator. Even though there should be one element at index 1 if a correct path is entered.

Finally, The End

I should not refer to this as the end, since part 2 is still to come! Anyway, goodbye for today, and subscribe to the mailing list to get notified when I post part 2! Good byeeeeeeee!

Discussion (0)