Writing Express Middleware to Modify the Response

I recently had a need for some Express middleware that would track any change to a variable, and send the details of any changes in the response, but only if the response is JSON data. This turned out to be rather more interesting delve into ExpressJS than I expected, and I thought the details of it were worth a post detailing how to do it, and my findings.

The first thing you notice when writing Express middleware functions is that they take three arguments (I’m skipping error-handling middleware deliberately), the request, the response and a next() function that triggers the next step in the processing chain. The next function doesn’t typically take any arguments, instead you’re expected to modify the request and response objects to expose or capture any changes you want.

This post will show you how to capture any changes to a variable (we’re going to pretend all our users are playing a game and we have a leader-board), we want to track any changes that happen during the request and report both the changes and the current state of the variable in every response. I’m going to assume some other middleware has injected a user property onto the request. First off, this is what the code will look like:

const leaderboard = require('./leaderboard');
function leaderboardTracking(req, resp, next) {
  const user = req.user;
  const startingPosition = leaderboard.getUserPosition(user);
  const json_ = resp.json; // capture the default resp.json implementation

  resp.json = function(object) {
    const endPosition = leaderboard.getUserPosition(user);
    object['leaderboard_info'] = {
      'delta':    endPosition - startPosition,
      'position': endPosition,
      'score':    user.score
    };

    json_.call(resp, object);
  };

  next();
}

So in this example we swap out the json function with our own delegate implementation, but you’ll notice we leave the send function alone. The send function will delegate to the json function if it’s given a plain JavaScript object, and json in-turn uses send after stringifying the object.

You’ll also notice that the code doesn’t just invoke the captured json_ function, it uses the call function and specifies the response as this. The json function in Express expects to be invoked within the context of the response object, so we need to keep it that way.

That’s it really, it’s not a terribly complicated pattern, but it can be extremely powerful because it bounds the request / response cycle end-to-end.

Advertisements

EoD SQL Applied – Part 4 / 5 (JavaScript)

JavaScript vs. Web Applications

So far in this series we’ve discussed using DataSets for Swing applications and DataIterators for web-applications. Why would I now bring in JavaScript as something outside of “web-application”? JavaScript applications have very different requirements to a normal web-application. Where a normal web-application has little ability to do things like preload data (like the next page), a JavaScript application may (for example) download the entire data-set and then display it in pages. This next section is about binding to JSON for JavaScript applications.

First thing to remember here is that an EoD SQL DataSet is a List and thus compatible with the Collections API. For this example we’re going to be working with the outstanding GSON API from our friends at Google. Our objective here is to minimize the amount of time spent between the Database and pushing the data to the client. Because GSON doesn’t appear to support Iterable object out-of-the-box, we’re going to start off using a DataSet.
Read the rest of this entry »

Eod SQL Applied – Part 1/5 (Introduction)

Introduction

This is the first part of a series of posts, dedicated to how best to apply EoD SQL in different types of applications. Each post in this series will cover a specific type of application, and the different parts of EoD SQL that generally work best within those applications. The articles may dive fairly deep into the workings of the API, but at the end you’ll have a much better idea of where things fit in, and how they fit together.

EoD SQL well understands that (a) people like to do things differently and (b) one solution is not right for everything. While under the hood: any one part of EoD SQL works much the same way as any other part, as you climb the structural ladder, things begin to behave very differently. These behaviors have a massive performance and memory impact on your application and how you will be treating the underlying database drivers.

What we’ll be covering

  1. Swing Applications
  2. JSP / Servlets and “Related Technologies”
  3. JavaScript / JSON Applications
  4. GWT Applications

Although you could go with the “one size fits all” route (and EoD SQL would still perform wonderfully), the objective of these posts is to expose you to the different flavors of EoD SQL data structures and get you thinking about how you can mix and match them in your application to produce different results.

An automated JSON Encoder and Decoder for Java

I posed a little while ago that I’d implemented a JSON Encoding that worked a bit like Java Serialization. It works as such in that you don’t need to encode the objects by hand. As long as you follow some basic rules, the code will automagically turn your Java objects into JSON, and the JSON back into Java objects again. Well, I finally got my act together and the implementation is below. Consider this Public Domain code now! If it doesn’t work for you, it’s not my problem (that said, I’d like to know if it doesn’t work).

Before The implementation, heres a few things to know about it:

  1. It solves the Date problem in such a way that it’s transparent to the JavaScript code!
    1. Dates are encoded as “new Date(UTCTime)”
    2. They are decoded against a collection of date-formats (listed at the top of the JSONDecoder class)
  2. The encoding and decoding work against Reader and Writer objects, and thus have declared IOExceptions
    1. They expect to be closely tied to the Reader and Writer provided by the Servlet Container
  3. They both conform to the Java Beans specs, so if it’s not a bean property, it’s ignored
  4. The decoder can handle both the abstract Collection types and concrete types
    1. public void setUserList(List<User> users)
    2. public void setUserList(ArrayList<User> users)
    3. The Collections must have a solid type declared as their content (in the generic)
  5. Map objects are encoded as JavaScript objects
    1. Map keys must therefore be Strings
    2. The Map keys should be valid JavaScript identifiers

If you are going to use this code, I would appreciate a comment here (just to let me know).

Read the rest of this entry »

Java to JSON like Serialization

I recently decided to write myself a JSON Encoder class that would allow me to build JSON Strings from my Java code. I didn’t like the look of any of the existing JSON API’s for Java, since they all seem to require you to build the JSON Strings by hand. So I wrote a class that gets invoked like this:


public class User {
    private static final JSONEncoder<User> USER_ENCODER = new JSONEncoder<User>(User.class);

    // other fields, getters and setters go here

    public String toJSONString() {
        return USER_ENCODER.encode(this);
    }

    public void writeJSON(final Writer out) {
         USER_ENCODER.encode(this, out);
    }
}

All very nice and easy. However, theres one small problem: how do I turn the JSON from the client back into Java objects? Easy, a JSONDecoder class. This class is invoked totally differently to the Encoder.


public class UserServlet extends HttpServlet {
    public void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws IOException, ServletException {

        final User user = JSONDecoder.decode(req.getReader(), User.class);
    }
}

As you can see, both are very easy to work with from the outside. They also take Dates and Times into account by allowing for the use of “new Date()” constructors in the JSON String, which means no Date decoding on the client side. The implementations are a bit long to post on my blog, if anyone is interested in the implementations: leave a comment.