Simple server side router for Meteor
Tags: meteor
Published: 2020-07-12 01:27:12

Or how I modernized Picker router, but first some background on what is going on in Meteor on the server side when it comes to routing.

I'm using React with `react-router` without SSR. Recently I decided that I wanted to add RSS for my blogs and I wanted it to be generated on the server. So I needed some way to establish a route on the server and have it execute my function.

Now, going back in history this is relatively easy with Meteor centric routers like `iron:router` or `flow:router` where we could set server routes. Under the hood Meteor uses [connect](https://www.npmjs.com/package/connect) so there was already an infrastructure to get server requests and is accessible via `meteor/webapp`.

```js
import { WebApp, WebAppInternals } from 'meteor/webapp'
```

In my case my previous use was to manually set browser policy headers without any package (but that is for another article). Now you can easily get server requests and intercept static routes as we see in `connect` documentation (here adjusted for Meteor):

```js
WebApp.rawConnectHandlers.use('/foo', function fooMiddleware(req, res, next) {
  // req.url starts with "/foo"
  next()
})
```

Now if you want to add params into the route you are out of luck. Connect is a minimalist library and doesn't do param resolution. Now there are quiet a few routers for `node`, most famously `express`. But that is an overkill since we already have the basics and integrating any of them would most likely break your Meteor app. So what are you to do if you don't want to build it yourself. Thankfully there already is a solution.

After few hours I found an old project `meteorhacks:picker` which provides a server side router for Meteor (it is the part that handles server side routing for `flow:router`) and plays nice with anything else you might have setup.

Now the problem is that `meteorhacks:picker` is 5 years old! Probably not something you want to add to a new project. Well, worry not! I have done the work of modernizing the package and right now I'm [lobbying](https://github.com/Meteor-Community-Packages/organization/issues/50) for it to be moved to [Meteor Community Packages](https://github.com/Meteor-Community-Packages) so that we can update the package without having to create a new namespace on Atmosphere. So for now you can go to [my repository](https://github.com/StorytellerCZ/picker) and download the code into your packages folder.

## Use Picker
After that you can install picker (it will pick your local version):
```bash
meteor add storyteller:picker
```

Now on your server you can import Picker:
```js
import { Picker } from 'meteor/storyteller:picker'
```

For my RSS I want to only handle GET requests so I create a filter:
```js
const rssRoutes = Picker.filter(function(req, res) {
  return req.method === "GET"
})
```

After that I can now create my routes to handle building the RSS:
```js
rssRoutes.route('/blog/:userId/rss', (params, req, res) => {
  if (!params.userId) return return404(res)
  const data = articlesData(BLOG_TYPES.USER, params.userId)
  if (!data) return return404(res)
  res.setHeader('content-type', 'application/rss+xml')
  res.writeHead(200)
  res.end(buildRss(data))
})
```
Simple, isn't it? `params` passes in the params you have defined in the route and under `params.query` you will get an object with search parameters from routes like `/blog/storyteller/rss?output=xml`.

## Where to get this?
UPDATE: My version of Picker has become part of Meteor Community Packages and you can get it from [Atmosphere](https://atmospherejs.com/communitypackages/picker).

So where is this available? Currently you can download the code from [my repository](https://github.com/StorytellerCZ/picker) to your local packages.

Not ideal, I know. I have [opened an issue](https://github.com/meteorhacks/picker/issues/55) on the original Picker to move it to [Meteor Community Packages](https://github.com/Meteor-Community-Packages/organization/issues/50), but given that Arunoda has not been responsive we will most likely have to take my codebase and publish it under MCP namespace. But hopefully in few weeks I will have an update here.

--------
If you like my work, please consider supporting me on [GitHub Sponsors ❤️](https://github.com/sponsors/StorytellerCZ).