This time i want show you how to create your own REST testing application. For this demonstration i use Python, Tkinter and some Python libraries. At the end of this tutorial you can extend the application with more features like “show headers”, “store requests/responses”, “run automatically” and so on.
Preparation
- install Python > 2.7 (Tkinter included)
- install Requests: HTTP for Humans
- install Python Data Validation for Humans
requests==2.8.1
validators==0.9
Example
# -*- coding: utf-8 -*-
from Tkinter import Tk, FALSE
class BaseTkGui(object):
"""Define basic TK GUI"""
def __init__(self, window_title, window_resizable):
"""Constructor for Tkinter GUI"""
self._root = Tk()
self._root.title(str(window_title))
if not bool(window_resizable):
self._root.resizable(width=FALSE, height=FALSE)
else:
self._root.columnconfigure(0, weight=1)
self._root.rowconfigure(0, weight=1)
def start_app(self):
"""Start TK loop"""
self._root.mainloop()
def quit_app(self):
"""Stop and quit application"""
self._root.quit()
# -*- coding: utf-8 -*-
from Tkinter import (Frame, OptionMenu, Entry, Button, StringVar, Label,
W, E, NO, END, SOLID)
from ttk import Treeview, Separator
from ScrolledText import ScrolledText
from BaseGui import BaseTkGui
class ApplicationTkGui(BaseTkGui):
"""Define application TK GUI"""
OPTIONS = ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS']
def __init__(self, window_title):
"""Constructor for specific application GUI"""
BaseTkGui.__init__(self, window_title, False)
self._method = None
self._url = None
self._tree = None
self._status = None
self._time = None
self._key = None
self._value = None
self._output = None
def build_frames(self):
"""Add all frames and start mainloop"""
self.__top_frame()
self.__middle_frame()
self.__bottom_frame()
self.start_app()
def prepare_req(self):
"""Overwritten method"""
pass
def _add_items(self):
"""Add items into TreeView at end"""
key = str(self._key.get())
value = str(self._value.get())
if key and value:
self._tree.insert("", "end", values=(key, value))
self._key.delete(0, END)
self._value.delete(0, END)
self._tree.bind("<Double-1>", self._delete_item)
def _delete_item(self, event):
"""Delete items from TreeView by ID"""
item = self._tree.identify_row(event.y)
self._tree.delete(item)
def __top_frame(self):
"""Top frame creator"""
self._method = StringVar(self._root)
self._method.set("GET")
frame = Frame(self._root)
frame.grid(column=0, row=0, sticky=W+E)
frame.grid_rowconfigure(0, weight=1)
frame.grid_columnconfigure(0, weight=1)
option = OptionMenu(frame, self._method, *self.OPTIONS)
option.grid(column=0, row=0, padx=5, pady=5)
self._url = Entry(frame, width=50)
self._url.grid(column=1, row=0, padx=5, pady=5)
self._url.configure(borderwidth=1, relief=SOLID)
self._url.configure(highlightthickness=0)
self._url.insert(0, 'http://')
submit = Button(frame, text='Submit', command=self.prepare_req)
submit.grid(column=3, row=0, padx=5, pady=5)
Separator(frame).grid(columnspan=4, row=1, sticky=W+E)
def __middle_frame(self):
"""Middle frame creator"""
frame = Frame(self._root)
frame.grid(column=0, row=1, sticky=W+E)
frame.grid_rowconfigure(0, weight=1)
frame.grid_columnconfigure(0, weight=1)
self._tree = Treeview(frame, columns=("Key", "Val"), selectmode='none')
self._tree.grid(columnspan=5, row=0, padx=5, pady=5, sticky=W+E)
self._tree.column('#0', stretch=NO, minwidth=0, width=0)
self._tree.heading('#1', text='Key')
self._tree.heading('#2', text='Value')
self._tree.configure(height=5)
key = Label(frame, text='Key:')
key.grid(column=0, row=1, padx=5, pady=5, sticky=E)
self._key = Entry(frame)
self._key.grid(column=1, row=1, padx=5, pady=5, sticky=W)
self._key.configure(borderwidth=1, relief=SOLID)
self._key.configure(highlightthickness=0)
value = Label(frame, text='Value:')
value.grid(column=2, row=1, padx=5, pady=5, sticky=E)
self._value = Entry(frame)
self._value.grid(column=3, row=1, padx=5, pady=5, sticky=W)
self._value.configure(borderwidth=1, relief=SOLID)
self._value.configure(highlightthickness=0)
add = Button(frame, text='Add new header', command=self._add_items)
add.grid(column=4, row=1, padx=5, pady=5)
Separator(frame).grid(columnspan=5, row=2, sticky=W+E)
def __bottom_frame(self):
"""Bottom frame creator"""
font_style = ('verdana', 10, 'normal')
frame = Frame(self._root)
frame.grid(column=0, row=2, sticky=W+E)
frame.grid_rowconfigure(0, weight=1)
frame.grid_columnconfigure(0, weight=1)
self._status = Label(frame, text='Response Status: -')
self._status.grid(column=0, row=0, sticky=W)
self._status.configure(fg='red', font=font_style)
self._time = Label(frame, text='Time: - ms')
self._time.grid(column=1, row=0, sticky=E)
self._time.configure(fg='red', font=font_style)
self._output = ScrolledText(frame)
self._output.grid(columnspan=2, row=1, padx=5, pady=5, sticky=W+E)
self._output.configure(height=12, borderwidth=1, relief=SOLID)
self._output.configure(highlightthickness=0)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests
import validators
from Tkinter import END
from ApplicationGui import ApplicationTkGui
class Application(ApplicationTkGui):
"""Define application behaviors"""
def __init__(self, window_title):
"""Constructor for application with title"""
ApplicationTkGui.__init__(self, window_title)
def run_application(self):
"""Start application"""
self.build_frames()
def prepare_req(self):
"""Prepare and validate request"""
headers = dict()
method = self._method.get()
url = self._url.get()
tree_ids = self._tree.get_children()
for i in tree_ids:
row = self._tree.item(i)
add = row['values']
headers[add[0]] = add[1]
if validators.url(url):
self.__do_request(method, url, headers)
def __do_request(self, method, url, headers):
"""Do request and print results"""
self._output.delete(1.0, END)
ses = requests.Session()
prepped = requests.Request(method, url, headers).prepare()
response = ses.send(prepped, verify=False, allow_redirects=True)
code = response.status_code
body = response.text
time_delta = response.elapsed
duration = time_delta.total_seconds()
status = 'Response Status: ' + str(code)
time = 'Time: ' + str(duration) + ' ms'
text = body[0:900] + ' ...'
self._status.configure(text=status)
self._time.configure(text=time)
self._output.insert(END, text)
if __name__ == '__main__':
RUN = Application('HTTPTester')
RUN.run_application()
Run application
# set access permissions
$ chmod u+x ./RESTme.py
# start application
$ python -B ./RESTme.py
The application should look like: