Giter Club home page Giter Club logo

express-api's Introduction

General Assembly Logo

Express as an API

Express, like Rails, can be used as an API. In fact, building APIs in Express, especially those that use MongoDB for persistence, led to the rising popularity of Node.

Express can be used for full-stack applications (those that have server-rendered views). However, we will use it purely as an API.

A customized template for Express is available at ga-wdi-boston/express-template. It includes authentication and common middlewares so that you can start developing an API right away.

Prerequisites

Objectives

By the end of this, developers should be able to:

  • Develop an Express API, leveraging architectural conventions from Rails.
  • Write five CRUD endpoints for an API resource using Express, Mongoose, and JavaScript.
  • Prevent unauthorized users from creating or changing data through the API.

Preparation

  1. Fork and clone this repository.
  2. Install dependencies with npm install.
  3. Verify monogdb is runnning with brew services list (Run brew services restart mongodb if not)
  4. Set a SECRET_KEY in the environment.
  5. Run the API server with npm start. If you want your code to be reloaded on change, you should npm install -g nodemon and use nodemon instead of npm start.

For development and testing, set the SECRET_KEY from the root of your repository using:

echo SECRET_KEY=$(/usr/local/opt/openssl/bin/openssl rand -base64 66 | tr -d '\n') >>.env

A Bookstore API

We've been hired to write an API for a local bookstore, 'Book Before You Leap'. They have plans to expand in the next few years, and they'll probably rival Amazon. Therefore, we've chosen Express because it's hip, and Mongo because it's Web Scale™.

Let's get acquainted with how we'll use Express.

Demo: An Example Express Controller

First, let's peek at our routes, since that's the layer that decides which code to run for any given request. Open config/routes.js and read through it. Look familiar?

Have a look in the app directory. It looks a bit like Rails, too.

In app/controllers/examples.js, we get our first taste of Express. What's the (req, res, next) signature on all our controller actions?

The req object is a http.IncomingMessage object. The res object is http.ServerResponse object. These are what we used in the node HTTP server. What about next?

More than one callback function can handle a route (make sure you specify the next object).

Express routing

That means more than one action can be run for a single request. In fact, that's how Express keeps boilerplate to a minimum; we did something similar with before_filters in Rails. Common functionality, like error handling, can be extracted into a middleware and run on any request you like. However, you must use next to propagate errors onward.

Likewise, res.json signals to Express that we're done working on our response. It's analogous to Rails' render method. If you don't use a terminal handler, Express will keep the connection open waiting for one. You and Express will both be frustrated and confused. Here's a list of terminal handlers. You will use res.json and res.sendStatus most frequently.

Response method What it means
res.end() End the response process.
res.json(jsObject) Send a JSON response.
res.redirect() Redirect a request.
res.sendStatus() Set the response status code and send its string representation as the response body.

Lab: Summarize Actions in Examples Controller

Practice reading unfamiliar code by annotating app/controllers/examples.js. As you read each controller action, keep the following questions in mind. You will be asked to answer them when we share our notes.

  • What is the purpose of this action?
  • Does it need a singular or plural resource to build its response?
  • How is the action handling errors?
  • Why do we need to check for the existence of a record after querying?
  • Where do we get IDs from?
  • Where do we get data from when creating or updating a record?
  • Which terminal handler is used to send a response?

Demo: An Example Express Model

Let's read app/models/example.js and answer the following questions together:

  • What library are we using to model our resources? Does it have anything to do with Express?
  • What does the underscore denote in _owner?
  • Where should we go to find out more about an owner?
  • Why aren't we using an arrow function for the virtual attribute length?

Lab: Create an Example

Start the server and try creating an example by issuing a POST /examples. What happens? You might find some help in the scripts directory.

When you've created an example, try using its ID to request it via GET /examples/:id. Then, create another and check your work with GET /examples.

Code-Along: POST /books

Only authenticated users should be able to create a book.

Let's create our book model together, and one controller action. Don't forget a route!

Make sure to save a reference to the user that created the book so we can user it later to check ownership.

We'll need to write a test script to check our work. We'll save it as scripts/books-create.sh.

We're done when we see a response similar to this one:

Expected response:

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8

{
  "book": {
    "__v": 0,
    "updatedAt": "2016-03-09T03:23:58.000Z",
    "createdAt": "2016-03-09T03:23:58.000Z",
    "_owner": "56df9716c19957cb0d836c4a",
    "title": "Invisible Monsters",
    "author": "Chuck Palahniuk",
    "price": 10.99,
    "_id": "56df974ec19957cb0d836c4d"
  }
}

Code-Along: GET /books

Visitors to the client web application should be able to see all the books without being logged in.

We will need to write a controller action and a test script.

Expected response:

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8

{
  "books": [
    {
      "_id": "56df974ec19957cb0d836c4c",
      "updatedAt": "2016-03-09T03:23:58.000Z",
      "createdAt": "2016-03-09T03:23:58.000Z",
      "_owner": "56df9716c19957cb0d836c4a",
      "title": "Between the World and Me",
      "author": "Ta-Nehisi Coates",
      "price": 12.99,
      "__v": 0
    },
    {
      "_id": "56df974ec19957cb0d836c4d",
      "updatedAt": "2016-03-09T03:23:58.000Z",
      "createdAt": "2016-03-09T03:23:58.000Z",
      "_owner": "56df9716c19957cb0d836c4a",
      "title": "Invisible Monsters",
      "author": "Chuck Palahniuk",
      "price": 10.99,
      "__v": 0
    }
  ]
}

Lab: GET /books/:id

Visitors to the client web application should be able to see any book without being logged in.

You will need to write a controller action and a test script.

Expected response:

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8

{
  "book": {
    "_id": "56df974ec19957cb0d836c4c",
    "updatedAt": "2016-03-09T03:23:58.000Z",
    "createdAt": "2016-03-09T03:23:58.000Z",
    "_owner": "56df9716c19957cb0d836c4a",
    "title": "Between the World and Me",
    "author": "Ta-Nehisi Coates",
    "price": 12.99,
    "__v": 0
  }
}

Lab: PATCH /books/:id

Only authenticated users should be able to change a book. They should not be able to change other users' books.

You will need to write a controller action and a test script.

Expected response:

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8

You may wish to retrieve the book you changed to check your work.

If a different user than the owner tries to make the change, you should instead see:

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8

{
  "error": {
    "message": "Not Found",
    "error": {
      "status": 404
    }
  }
}

Lab: DELETE /books/:id

Only authenticated users should be able to delete a book. They should not be able to delete other users' books.

You will need to write a controller action and a test script.

Expected response:

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8

If a different user than the owner tries to make the change, you should instead see:

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8

{
  "error": {
    "message": "Not Found",
    "error": {
      "status": 404
    }
  }
}

Additional Resources

Source code distributed under the MIT license. Text and other assets copyright General Assembly, Inc., all rights reserved.

express-api's People

Contributors

laurenfazah avatar payne-chris-r avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.