• Stars
    star
    138
  • Rank 264,508 (Top 6 %)
  • Language
    Go
  • Created over 11 years ago
  • Updated about 9 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Ripple is a REST API library for the Go programming language. Demo is available below:

Ripple, a REST API framework for Go

Ripple is a simple, yet flexible, REST API framework for the Go language (golang).

Since building REST APIs often involves a lot of boiler plate code (building routes, handling GET, POST, etc. for each route), the framework attempts to simplify this by making assumptions about the way REST APIs are usually structured. The framework is flexible though, so if the defaults get in the way, they can be changed.

Installation

To install the library, clone this git directory:

git clone https://github.com/laurent22/ripple.git

and import it in your main Go file using import ./ripple

Demo

A simple todo demo is available there: https://github.com/laurent22/ripple-demo

Usage

Have a look at demo/demo.go and demo/demo_client.go for a simple example of a REST API application.

In general, the steps to build a REST application are as follow:

package main

import (
	"./ripple"
	"./controllers"
	"net/http"
)

func main() {	
	// Build the REST application
	
	app := ripple.NewApplication()
	
	// Create a controller and register it. Any number of controllers
	// can be registered that way.
	
	userController := rippledemo.NewUserController()
	app.RegisterController("users", userController)
	
	// Setup the routes. The special patterns `_controller` will automatically match
	// an existing controller, as defined above. Likewise, `_action` will match any 
	// existing action.
	
	app.AddRoute(ripple.Route{ Pattern: ":_controller/:id/:_action" })
	app.AddRoute(ripple.Route{ Pattern: ":_controller/:id/" })
	app.AddRoute(ripple.Route{ Pattern: ":_controller" })
	
	// Start the server
	
	http.ListenAndServe(":8080", app)
}

Application

A Ripple application implements the net.http Handler interface and thus can be used with any Go server function that accepts this interface, including ListenAndServe or ListenAndServeTLS. To build a new application, call:

app := ripple.NewApplication()

Then, after having setup the controllers and routes (see below), call:

http.ListenAndServe(":8080", app)

This will create a REST API on http://localhost:8080

Ripple can also be used along other HTTP servers using http.HandleFunc() and accessing the ServeHTTP() function directly. For instance, to serve an HTML5/JS app under "/app" and the REST API under "/api", the following could be done:

// Handle the HTML5 app
http.HandleFunc("/app/", someHandleFunc)

// Handle the REST API	
app.SetBaseUrl("/api/")
http.HandleFunc("/api/", app.ServeHTTP) // Use the ServeHTTP function directly

// Start the server
http.ListenAndServe(":8080", nil)

Then the REST API will be at http://localhost/api/:8080, while the web application will be at http://localhost/app/:8080.

Controllers

A Ripple controller is a struct with functions that handle the GET, POST, PUT, etc. HTTP methods (custom HTTP methods are also supported). The mapping between URLs and controller functions is done via routes (see below). Each function must start with the method name, followed by the (optional) action name. Each function receives a ripple.Context object that provides access to the full HTTP request, as well as the optional parameters. It also allows responding to the request. The code below shows a very simple controller that handles a GET method:

type UserController struct {}

func (this *UserController) Get(ctx *ripple.Context) {
	// Get the user ID:
	userId, _ := strconv.Atoi(ctx.Params["id"])
	if userId > 0 {
		// If a user ID is provided, we return the user with this ID.
		ctx.Response.Body = this.userCollection.Get(userId)
	} else {
		// If no user ID is provided, we return all the users.
		ctx.Response.Body = this.userCollection.GetAll()
	}
}

In the above code, ctx.Params["id"] is used to retrieve the user ID, the response is provided by setting ctx.Response.Body. The body will automatically be serialized to JSON.

To handle the POST method, you would write something like this:

func (this *UserController) Post(ctx *ripple.Context) {
	body, _ := ioutil.ReadAll(ctx.Request.Body)
	var user rippledemo.UserModel
	json.Unmarshal(body, &user)
	ctx.Response.Body = this.userCollection.Add(user)
}

Finally, more complex actions can be created. For example, this kind of function can be created to handle a REST URL such as /users/123/friends:

func (this *UserController) GetFriends(ctx *ripple.Context) {
	userId, _ := strconv.Atoi(ctx.Params["id"])
	var output []rippledemo.UserModel
	for _, d := range this.friends {
		if d.UserId1 == userId {
			output = append(output, this.userCollection.Get(d.UserId2))
		} else if d.UserId2 == userId {
			output = append(output, this.userCollection.Get(d.UserId1))
		}
	} 
	ctx.Response.Body = output
}

Routes

The routes map a given URL to a given controller / action. Before being used in a route, the controllers must first be registered:

// Create some example controllers:

userController = new(UserController)
imageController = new(ImageController)

// And register them:

app.RegisterController("users", userController)
app.RegisterController("images", imageController)

Then the routes can be created:

app.AddRoute(ripple.Route{ Pattern: ":_controller/:id/:_action" })
app.AddRoute(ripple.Route{ Pattern: ":_controller/:id/" })
app.AddRoute(ripple.Route{ Pattern: ":_controller" })

Parameters can be defined by prefixing them with :; they are then accessible from the context object via ctx.Params["id"].

Route patterns also accept two special parameters:

  • _controller: Match any registered controller.
  • _action: Match any existing controller action.

For example, the routes above would match URLs such as "users/123", "images/7", "images/456/metadata", etc. You do not need to specify the supported HTTP methods - whether a method is supported or not is implied from the controller functions. For instance, if the controller has a GetMetadata method, then GET images/456/metadata is automatically supported. Likewise, if it does not have a DeleteMetadata method, DELETE images/456/metadata will not be supported.

Routing can be as flexible as needed. If the automatic mapping of _controller and _action doesn't do the job, it is possible to explicitly specify the controller and action. For example:

app.AddRoute(Route{ Pattern: "some/very/custom/url", Controller: "users", Action: "example" })

With the above route, doing GET some/very/custom/url would call UserController::GetExample

Models?

Ripple does not have built-in support for models since data storage can vary a lot from one application to another. For an example on how to connect a controller to a model, see demo/controllers/users.go and demo/models/user.go. Usually, you would inject a database connection or other data source into the controller then use that from the various actions.

Testing

Ripple is built with testability in mind. The whole framework is fully unit tested, and applications built with the framework can also be easily unit tested. Each controller method takes a ripple.Context object as parameter, which can be mocked for unit testing. The framework also exposes the Application::Dispatch method, which can be used to test the response for a given HTTP request.

Ripple API reference

See the Ripple GoDoc reference for more information.

License

The MIT License (MIT)

Copyright (c) 2013-2015 Laurent Cozic

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

More Repositories

1

joplin

Joplin - the privacy-focused note taking app with sync capabilities for Windows, macOS, Linux, Android and iOS.
TypeScript
45,447
star
2

rsync-time-backup

Time Machine style backup with rsync.
Shell
3,364
star
3

massren

massren - easily rename multiple files using your text editor
Go
1,338
star
4

joplin-android

Android releases for Joplin
234
star
5

so-sql-injections

SQL injection vulnerabilities in Stack Overflow PHP questions
PHP
161
star
6

wslpath

wslpath - Converts Unix and Windows format paths in WSL
PHP
92
star
7

fastcopy

FastCopy
C++
65
star
8

pmcctv

pmcctv - poor man's CCTV system in Go
Go
56
star
9

toml-go

Toml parser in Go
Go
47
star
10

joplin-nextcloud

Joplin Web API for Nextcloud
JavaScript
45
star
11

appetizer

Official repository for Appetizer, the open source application launcher, or dock, for Windows.
C++
36
star
12

go-sqlkv

An SQL-based key/value store for Golang
Go
36
star
13

ical-go

iCal package for Go (Golang)
Go
35
star
14

pmcam

Poor man's video capture with motion detection in Bash
Shell
34
star
15

go-trash

Cross-platform package to move stuff to the OS trash
Go
19
star
16

Kohana-Mustache

A Mustache module for Kohana.
PHP
14
star
17

github-actions-logs-extension

Display GitHub Action Raw log in color, converting the Ansi colors to HTML
JavaScript
11
star
18

joplin-turndown-plugin-gfm

Fork of turndown-plugin-gfm for Jopin
JavaScript
9
star
19

simple-gettext

C++
9
star
20

joplin-turndown

JavaScript
8
star
21

gannet

A database migration tool in PHP
PHP
7
star
22

joplin-renderer

Markdown and HTML renderer for Joplin
JavaScript
5
star
23

proxy-tester

Go application to test web proxies
Go
5
star
24

ripple-demo

A demo application for Ripple, the REST API framework for Go
Go
5
star
25

joplin-plugin

JavaScript
4
star
26

kimai-desktop

Desktop client for Kimai
C++
4
star
27

poparser

This a PHP parser for Gettext PO files. It can extract the strings and translations from the file. It can also provide statistics about the state of the translation - i.e. how many strings have been translated, how many are fuzzy, etc. which is useful to provide translation reports.
PHP
4
star
28

homebrew-massren

Homebrew tap for massren. NOTE: massren is now officially on Homebrew at https://github.com/Homebrew/homebrew-core/blob/master/Formula/massren.rb
Ruby
3
star
29

laurent22.github.io

https://laurent22.github.io/so-injections/
HTML
3
star
30

tkwidgets

JavaScript
2
star
31

kache

Simple cache system for PHP with support for multiple drivers.
PHP
2
star
32

go-torrent

Golang package to build a torrent client
Go
2
star
33

laurent22

1
star
34

androidsync

Android Sync is a command line tool to synchronize an Android phone with Windows, Mac OS X or Linux via adb
Go
1
star
35

generator-joplin

Scaffolds out a new Joplin plugin
TypeScript
1
star
36

akview

Command line based image viewer and editor
C++
1
star
37

ipify-www

The public facing website for ipify.org.
HTML
1
star