Writing my first (very basic) API with Go & VueJs

Note:

This article is not a ‘you should do it this way’ manual.

I am teaching myself how to code and I managed to build an API to return data to a webpage using the following method – please feel free to share/give advice but please remember I am still learning myself so this might not be 100% best practice.

If you’re new to programming and are interested in how to get a very basic API working, I hope this is useful to you in some way ūüôā

What is an API?

Petr Gazarov wrote a great article on FreeCodeCamp’s blog here.

To summarise in simple terms:

APIs allow users to complete actions without having to leave your website. The API is a set of dedicated URLs that return pure data responses. This can then be interpreted and used on a front end/website for example.

Why would companies want to use APIs?

An API allows for separation between the frontend and backend of an application ( or service to service connections). You can build multiple frontends that can handle the data stored in a separate service, i.e a desktop, phone app & web app could use an API to access the same data/ backend. If you contain all of your website features in one project (known as monolithic) it is harder to manage – changing something in the frontend could break some backend function. Separating the backend out means that you can work on it in isolation without impacting your frontend and vice versa.

Visual example:

Monolithic project

Microservices project

The dotted lines represent the API – they are calls between different services for data. In this post, we will build a project with a frontend and one backend API service. I.e. Website > Friends List.

 

So what did I do…

I started by building a really simple front end. I used Nuxt & VueJs for my front end & while this isn’t going to be a tutorial on how to use VueJs, here are the basic steps I used to get that going:

npm install -g @vue/cli @vue/cli-init
vue init nuxt-community/starter-template <project-name>
cd <project-name>
npm install
npm run dev

The application is now running on http://localhost:3000
Steps taken from Nuxt docs here

It really doesn’t matter for the sake of this exercise what you do with the web page, add or remove whatever you like, but once you’re happy you need to add a button that is going to make an API call out to another service to return some data:

Something like this will do the job ->

my <project-name> = myProject

File: myProject/App.vue

<v-flex xs12>
    <v-btn
        @click="getAPI"
        color="error"
    >Call an API</v-btn>
    <h2 v-if="info">{{ info }}</h2>
    <h2 v-else>{{ message }}</h2>
</v-flex>

The @click="getAPI" tells us that on the click of this button we are going to call a function called getAPI. This function will either return INFO or MESSAGE. Depending on which one returns will determine which h2 element will display using the ‘v-if / v-else’. You will therefore need to add a couple of ‘data’ objects to handle this INFO/MESSAGE once it is returned:

You will need to add a section (full image of the complete code shown further down this page) and enter your data object like so:

File: myProject/App.vue


    export default {
        data: () => ({
            info:"",
            message:""
        })
     }

Lets write our function…

You will need to install ‘axios’, which is an ‘HTTP client for the browser and node.js’ – it is basically what is going to help us make requests for information from our api. It allows us to make ‘GET/POST/DELETE’ requests to a url, interacting with our service.

So go back to your terminal, in your project directory (in the nuxt steps above, ) and type the following:

npm install --save axios

Simples.

Now back in your Vue project (where you have your button) and inside the section, import axios so that it can be used in your Vue app, (this needs to be above the ‘export default you previously added’:

File: myProject/App.vue

import axios from 'axios';

The function will then be added into a ‘methods’ section below ‘data’:

File: myProject/App.vue

methods: {
    getAPI () {
        axios
        .get('YOUWILLADDAURLHERESOON')
        .then(response => (this.info = response.data.something))
        .catch(error => {
            this.message="API is not running"
            console.log(error);
        });
    }
}

Lets break this out line by line ->

  • get API () is the function name that we call from our button.
  • axios is the HTTP client we are about to make some requests with
  • .get is the request type we are making – we want to GET information. We want to give it 1 argument, which will be the URL of the backend service’s server (our API), once we have that!). Placeholder text for now
  • .then as implied is what we want to do next – it only runs if the .get() was successful. We want to take the response from our .get, and assign something in it to our data object ‘info’ – this is accessed by using ‘this.info’. We can placeholder this ‘thing’ for now.
  • If the .get() fails or the API is not running, we do not run .then(), we run .catch() – and fill in our v-else so the the user understands when they click the button, why information is not returning, we use the .catch for this.

This is your frontend Vue app pretty much ready – we know we have some placeholder text to come back to once the server is running on our API, so for now your button is not going to work and your going to see horrible console messages, lets get on and fix that.

In my own project, I put my button in a separate page, this is my full code for that page:

If you have ‘npm run dev‘ running in your terminal for this directory, you will be able to see your button by visiting localhost:3000 in your browser – the button for now should only return the error message ‘API is not running’ and there will be a lot of console errors due to the unfinished placeholder text.

Our API!

I wrote my backend service in go, so that is what I’ll show you in this post.

Start by installing go:

https://golang.org/dl/ – select your OS and the download should begin

The docs on the page above should show you where the go package is installed, on mac it goes here –¬†/usr/local/go/bin¬†directory

You will then need to set your GOPATH, follow instructions here.

We need to create a new directory, lets call it src/ourService & create our go file in here

export GOPATH=$HOME/go
cd $GOPATH
mkdir src/ourService
cd src/ourService
vim main.go (if you'd rather not use terminal, feel free to create this file and then open it in your IDE of choice!)

We then need to start coding our API, remember this is going to be a very, very simple service – we’re just going to create a JSON object with some text to reply with!

Here’s the code, (again not a go tutorial but so that you understand what it is doing! I am still learning go myself but I will try to explain as best as possible!)

File: main.go

package main

import (
  "fmt"
  "net/http"
)

func giveData(w http.ResponseWriter, r *http.Request) {
  w.Header().Set("Access-Control-Allow-Origin", "*")
  lovelyData := `{"hello": "'Hello from the APIIIIII' - Adele, 2015"}`
  fmt.Fprintf(w, lovelyData)
}

func main() {
  http.HandleFunc("/giveData", giveData)
  if err := http.ListenAndServe(":8080", nil); err != nil {
    panic(err)
  }
}
  • ‘package main’ is required by go to run your program, it tells the go compiler to treat this file as an executable file.
  • imports are the different built in (or third-party) packages we want to use in our go service – we will be using fmt (which formats for example console logs/printed messages) and net/http which is how we will run a server in our go service.
  • All endpoint you want to use in this API must be reigstered via the http.HandleFunc, in our example we have only one, ‘/givedata’ which we register to call giveData().
  • We start running a server via the http.ListenAndServe on port :8080¬†which blocks indefinitely, unless there is a critical error i.e. the port is already in use. We have error handling in this function which displays that error if encountered- helpful for debugging!
  • If the HTTP server is hit at the url ending ‘/givedata’. It will run the function registered above – aptly named, giveData().
  • In our giveData() function, it takes 2 arguments, an HTTP response writer – which we will use to set a header and also to send the data back to our frontend Vue app. And it also takes an HTTP request i.e what our vue app is requesting from our go service
  • I found out the long, hard way, that running 2 separate services locally runs into issues, as you cannot by default call from one local machine to another. So the first line of our ‘giveData’ function, is setting a header that allows access from the the vue app request to our go service data. You can read more about this kind of issue here.
  • Our function also contains our ‘lovelyData’ which is a JSON object containing 1 key value pair. You can make this anything you like, I opted for a crap joke. A better practice would be to store information in an object, then use JSON marshal to convert the object data to a string -> read more.
  • Finally, we are going to send the data requested via the http.Request (in our Vue app, the .get request will want to ask for the key, and we will return the value for that key – we will add this shortly)

If you now go to your terminal, in your /ourService directory, run:

go build

This will create an executable version of your file, it will be named after your directory. You can then run:

./ourService

And your go http server should be running – go to your browser and type localhost:8080/givedata and in your browser you should see your JSON object – wooo you’re API is working!

Now we need to combine the 2 services so that we can make calls from our Vue app to ourService to return some data!

Back in your vue project, we need to add the URL of ourService into the .get call that we put placeholder text (in our go application we gave the port :8080 and it is running on localhost), and we also need to update the response.data.SOMETHING to ask for the specific key name we gave our JSON object.  Your script section should now look like ->

So when we click our button, we will trigger the function getAPI(), which uses axios to make a get request to localhost:8080 (this is where we told our go service to run- make sure you still have a terminal running the ./ourService command, otherwise your go http server will stop!).

We want to call the endpoint localhost:8080/giveData because we know that triggers the function giveData in our go service.

We then update the .then, to say look at the value under response.data.hello (response.data would return the whole lovelyData object, we only want whats inside one key value pair) and we want to save this to our this.info variable in our Vue app so that it can be used on the page.

So in your terminal you should have 2 tabs open, your go/src/ourService – which should be running the command ./ourService to run the go http server.

And your other tab should be in your vue project and you need to run npm run dev (if you’re not already) to run the server here. Go to localhost:3000 to see the app in the browser.

Your button should display and when clicked on, you should see your data populate in an h2 format below the button!

To test the function in your Vue app works correctly, kill the service in your go project (ctrl/cmd + c) and click the button again, you should now see your error message ‘API is not running’ instead!

—————————————————————————————————————————–
I hope this has helped with some basics of what an API is and how it could be used – it is only a very basic level but hopefully now you can see the potential! I am very welcome to polite, constructive feedback. As mentioned, I am learning myself and this may not be the best way to get an API working, or best practices for writing in go or vuejs but I gave it a go using lots of different resources and got the outcome I was after using this method – but I am very keen to improve, so please feel free to leave a comment!

 

More reading:

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.