After completing the first 2 specifications in the last post, this week focus is on completing the 3rd spec - a wiki search functionality.


▶️ 3rd Specification ↑top

Search: Allow the user to type a query into the search box in the sidebar to search for an encyclopedia entry.

  • If the query matches the name of an encyclopedia entry, the user should be redirected to that entry’s page.
  • If the query does not match the name of an encyclopedia entry, the user should instead be taken to a search results page that displays a list of all encyclopedia entries that have the query as a substring. For example, if the search query were Py , then Python should appear in the search results.
  • Clicking on any of the entry names on the search results page should take the user to that entry’s page.

▶️ Django Learning ↑top

Before jumping🦘 into what I have learnt, below is a demo of the 3rd spec. Demo of 3rd Spec

1️⃣ View must return an HttpResponse ↑top

The error❌ "The view didn't return an HttpResponse object. It returned None instead" is shown when a search query GET request is sent to the server.

  • The index() function shown below is the function the server routes to when the GET request is received.
def index(request):
    if request.GET.get('q'):
        search(request, request.GET['q'])
    else:
        return render(request, "encyclopedia/index.html", {
            "entries": util.list_entries()
    })

# ...
# ...

def search(request, query):
    fuzzy_match = []
    # ...
    # ...
    return render(request, "encyclopedia/result.html", {
        "query": query,
        "results": fuzzy_match
    })

As with many mistakes, when revisited it looks incredible obvious. This time the root cause is lack of a return statement when calling search() . This stackoverflow question points me to the right direction when I was debugging this issue.

2️⃣ Django Cross-Site Scripting protection (XSS👿) ↑top

When working on rendering the query string in the scenario that no result matches the query string, I noticed the possibility of XSS.

A simple illustration that I had in mind is a query as shown below:

http://127.0.0.1:8000/?q="</li></ul><script>alert("test")</script>

OR simply enter the text below into the search box

"</li></ul><script>alert("test")</script>

XSS vulnerability in action 👾 Alt Text

Fortunately Django has autoescape (documentation) on by default😇. Thus the demo above will not be possible.

It can be made possible to confirm the possibility of XSS by explicitly turning off autoescape .

{% autoescape off %}
    {{ untrusted user controlled input text to be rendered }}
{% endautoescape %}

▶️ Conclusion ↑top

That's all for this post, next up - creating and editing wiki pages!

P/S: On related note regarding XSS, I imagine it will not be possible for XSS to occur by using the wiki page creation too. Will certainly keep you posted if it turns out otherwise 😉

This post is also available on DEV.