Go middleware for monetizing your API on a per-request basis with Bitcoin and Lightning ⚡️

Overview

ln-paywall

GoDoc Build Status Go Report Card GitHub Releases

Go middleware for monetizing your API on a per-request basis with Bitcoin and Lightning ⚡️

Middlewares for:

A client package exists as well to make consuming LN-paywalled APIs extremely easy (you just use it like the standard Go http.Client and the payment handling is done in the background).

An API gateway is on the roadmap as well, which you can use to monetize your API that's written in any language, not just in Go.

Contents

Purpose

Until the rise of cryptocurrencies, if you wanted to monetize your API (set up a paywall), you had to:

  1. Use a centralized service (like PayPal)
    • Can shut you down any time
    • High fees
    • Your API users need an account
    • Can be hacked
  2. Keep track of your API users (keep accounts and their API keys in some database)
    • Privacy concerns
    • Data breaches / leaks
  3. Charge for a bunch of requests, like 10.000 at a time, because real per-request payments weren't possible

With cryptocurrencies in general some of those problems were solved, but with long confirmation times and high per-transaction fees a real per-request billing was still not feasable.

But then came the Lightning Network, an implementation of routed payment channels, which enables real near-instant microtransactions with extremely low fees, which cryptocurrencies have long promised, but never delivered. It's a second layer on top of existing cryptocurrencies like Bitcoin that scales far beyond the limitations of the underlying blockchain.

ln-paywall makes it easy to set up an API paywall for payments over the Lightning Network.

How it works

With ln-paywall you can simply use one of the provided middlewares in your Go web service to have your web service do two things:

  1. The first request gets rejected with the 402 Payment Required HTTP status, a Content-Type: application/vnd.lightning.bolt11 header and a Lightning (BOLT-11-conforming) invoice in the body
  2. The second request must contain a X-Preimage header with the preimage of the paid Lightning invoice (hex encoded). The middleware checks if 1) the invoice was paid and 2) not already used for a previous request. If both preconditions are met, it continues to the next middleware or final request handler.

Prerequisites

There are currently two prerequisites:

  1. A running Lightning Network node. The middleware connects to the node for example to create invoices for a request. The ln package currently provides factory functions for the following LN implementations:
    • lnd
      • Requires the node to listen to gRPC connections
      • If you don't run it locally, it needs to listen to connections from external machines (so for example on 0.0.0.0 instead of localhost) and has the TLS certificate configured to include the external IP address of the node.
    • c-lightning with Lightning Charge
      • Run for example with Docker: docker run -d -u `id -u` -v `pwd`/data:/data -p 9112:9112 -e API_TOKEN=secret shesek/lightning-charge
      • Vanilla c-lightning (without Lightning Charge) won't be supported as long as c-lightning's RPC API only works via Unix socket and cannot be used as a remote server, because this is not a good fit for potentially multiple web service instances elastically scaled across a cluster of host machines
    • eclair (not implemented yet - PRs Welcome )
    • Roll your own!
      • Just implement the simple wall.LNClient interface (only two methods!)
  2. A supported storage mechanism. It's used to cache preimages that have been used as a payment for an API call, so that a user can't do multiple requests with the same preimage of a settled Lightning payment. The wall package currently provides factory functions for the following storages:
    • A simple Go map
      • The fastest option, but 1) can't be used across horizontally scaled service instances and 2) doesn't persist data, so when you restart your server, users can re-use old preimages
    • bbolt - a fork of Bolt maintained by CoreOS
      • Very fast, doesn't require any remote or local TCP connections and persists the data, but can't be used across horizontally scaled service instances because it's file-based. Production-ready for single-instance web services though.
    • Redis
      • Although the slowest of these options, still fast and most suited for popular web services: Requires a remote or local TCP connection and some administration, but allows data persistency and can even be used with a horizontally scaled web service
      • Run for example with Docker: docker run -d -p 6379:6379 redis
        • Note: In production you should use a configuration with password (check out bitnami/redis which makes that easy)!
    • groupcache (not implemented yet - PRs Welcome )
    • Roll your own!
      • Just implement the simple wall.StorageClient interface (only two methods!)

Usage

GoDoc

Get the package with go get -u github.com/philippgille/ln-paywall/....

We strongly encourage you to use vendoring, because as long as ln-paywall is version 0.x, breaking changes may be introduced in new versions, including changes to the package name / import path. The project adheres to Semantic Versioning and all notable changes to this project are documented in RELEASES.md.

Middleware

The best way to see how to use ln-paywall is by example. In the below examples we create a web service that responds to requests to /ping with "pong", using Gin as the web framework.

package main

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/philippgille/ln-paywall/ln"
	"github.com/philippgille/ln-paywall/storage"
	"github.com/philippgille/ln-paywall/wall"
)

func main() {
	r := gin.Default()

	// Configure middleware
	invoiceOptions := wall.DefaultInvoiceOptions // Price: 1 Satoshi; Memo: "API call"
	lndOptions := ln.DefaultLNDoptions           // Address: "localhost:10009", CertFile: "tls.cert", MacaroonFile: "invoice.macaroon"
	storageClient := storage.NewGoMap()          // Local in-memory cache
	lnClient, err := ln.NewLNDclient(lndOptions)
	if err != nil {
		panic(err)
	}
	// Use middleware
	r.Use(wall.NewGinMiddleware(invoiceOptions, lnClient, storageClient))

	r.GET("/ping", func(c *gin.Context) {
		c.String(http.StatusOK, "pong")
	})

	r.Run() // Listen and serve on 0.0.0.0:8080
}

This is just the most basic example. See the list of examples below for examples with other web frameworks / routers / just the stdlib, as well as for a more complex and useful example.

List of examples

Follow the links to the example code files.

Simple examples to show the use for the different web frameworks / routers / just the stdlib:

More complex and useful example:

Client

package main

import (
	"fmt"
	"io/ioutil"

	"github.com/philippgille/ln-paywall/ln"
	"github.com/philippgille/ln-paywall/pay"
)

func main() {
	// Set up client
	lndOptions := ln.LNDoptions{ // Default address: "localhost:10009", CertFile: "tls.cert"
		MacaroonFile: "admin.macaroon", // admin.macaroon is required for making payments
	}
	lnClient, err := ln.NewLNDclient(lndOptions)
	if err != nil {
		panic(err)
	}
	client := pay.NewClient(nil, lnClient) // Uses http.DefaultClient if no http.Client is passed

	// Send request to an ln-paywalled API
	res, err := client.Get("http://localhost:8080/ping")
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	// Print response body
	resBody, err := ioutil.ReadAll(res.Body)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(resBody))
}

You can also view this example here.

Related Projects

Issues
  • Some logs don't contain a timestamp

    Some logs don't contain a timestamp

    Example:

    [GIN-debug] Listening and serving HTTP on :8080
    Creating invoice for a new API request
    2018/09/02 22:45:30 Sending invoice in response: [...]
    [GIN] 2018/09/02 - 22:45:30 | 402 |    279.2542ms |       127.0.0.1 | GET      /qr?data=testtext
    

    So it's Creating invoice for a new API request, but also Checking invoice for hash [...] and potentially others.

    bug 
    opened by philippgille 4
  • A client can cheat if the backend has multiple endpoints with different prices

    A client can cheat if the backend has multiple endpoints with different prices

    Reproduction

    1. Create backend with 2 endpoints, "a" and "b"
      • "a" is 1 Satoshi, "b" is 10 Satoshis
    2. Client sends initial request to each
    3. Client pays invoice for "a"
    4. Client sends final request to "b", but with the preimage of the payment for "a"
    5. => Request works although the client didn't pay the related invoice

    Problem

    The middleware doesn't track which invoice was created for which endpoint, it doesn't know about the endpoints at all. It just checks if the preimage was already used as payment proof and then checks the LN node for the invoice's existence and settlement.

    Possible solution

    1. When the initial request arrives we're in the correct middleware instance, so we cache the URL path along with the preimage or its hash
    2. When the final request arrives we don't just check if it's valid (not used before, invoice settled), but also if the current request URL path is the same we previously cached. (Lookup via the preimage or its hash)

    Note 1: It's not enough to have an in-memory cache of just the preimage or its hash per middleware instance, because in case of a horizontally scaled web service the caches wouldn't work properly anymore. It's probably best to use the existing storage client implementations, so the web service developer can choose for example Redis when he wants to scale horizontally.

    bug 
    opened by philippgille 2
  • Add package for client-side functionality

    Add package for client-side functionality

    Currently when a developer uses an API that's paywalled with ln-paywall (or ElementProject's paypercall and potentially other projects in the future), he has to take care of:

    • Sending two physical requests for one logical one
    • Handling the 402 response
    • Establishing a connection to his Lightning Network node by himself and calling its RPC / HTTP API

    All by himself.

    This can be easily wrapped in a way so that the developer only has to create one instance of a client, similar to the net/http.Client, create a single net/http.Request and then call client.Do(...). Just as with the net/http.Client. All the payment handling can happen automatically in the background.

    The first goal should be a minimal working version. More advaned features should be added in the future with separate issues created for each feature.

    Minimal working version:

    • Connects to and works with lnd
    • No convenience methods (Get(...), Post(...)), just Do(...)
      • Are they exposed by the embedded HTTP client? Can they be hidden in that case?
    • No configuration like "only pay if the amount in the invoice is <= x BTC", just always pay the invoice

    Future features:

    • Support other LN node implementations
    • Make payments configurable, e.g. "only pay if the amount in the invoice is <= x BTC"
    • ...
    enhancement 
    opened by philippgille 1
  • Add reporting of code coverage

    Add reporting of code coverage

    1. Add code coverage analysis, for example: go test -v -race -coverprofile="coverage.txt" -covermode=atomic ./...
    2. Add reporting to service like Codecov or Coveralls
    3. Add badge to README

    See:

    • https://blog.golang.org/cover
    • https://github.com/codecov/example-go
    duplicate 
    opened by philippgille 1
  • Add groupcache as storage implementation

    Add groupcache as storage implementation

    Groupcache is a distributed cache, but unlike Redis, it doesn't need an extra server - it connects to its peers directly. While skimming info about it I read that you can't update or delete entries, because it's just meant as the most simple cache, but that's currently sufficient for ln-paywall's needs.

    https://github.com/golang/groupcache

    enhancement 
    opened by philippgille 1
  • Clarify preimage format / encoding

    Clarify preimage format / encoding

    Currently the value in the "x-preimage" header is required to be Base64, because that's the format that's used in listed invoices when executing lncli listinvoices. Not only for preimages, but also for their hashes.

    But on the other hand the LightningClient's method LookupInvoice(...) expects a hex-encoded payment hash.

    That's why in our package, when receiving a request with a correct x-preimage header, we need to:

    1. Base64 Decode the preimage
    2. Sha256 the previous value
    3. Hex the previous value
    4. Send it to lnd

    So:

    1. Figure out which format is best for using in the header (Plain preimage, Base64 or hex)
    2. Change our implementation in case it's not Base64
    3. Document which format is expected
    enhancement 
    opened by philippgille 1
  • Improve performance by reusing the gRPC connection

    Improve performance by reusing the gRPC connection

    Currently a new gRPC connection to lnd is created for every request.

    It should be possible to create the gRPC connection only once when one of the middlewares is created, for example when NewHandlerFuncMiddleware(...) is called, but before the handler func is returned.

    func createHandlerFunc(invoiceOptions InvoiceOptions, lndOptions LNDoptions, storageClient StorageClient, next http.HandlerFunc) func(w http.ResponseWriter, r *http.Request) {
    	// <---- create the gRPC connection here and reuse it within the below func
    	return func(w http.ResponseWriter, r *http.Request) {
    

    Care must be taken regarding connections that are aborted/lost/..., for example due to a network error. Is it possible to reconnect with the existing connection object/ref?

    enhancement 
    opened by philippgille 1
  • Refactor middlewares

    Refactor middlewares

    Currently the middleware factory functions contain a lot of duplicated code. There should be only one web framework-independent function that contains the main middleware logic, and then web framework-specific implementations that handle the details of the used web frameworks.

    This PR contains that, including a fix for the middleware for Echo.

    opened by philippgille 0
  • Bad error responses when using the Echo middleware

    Bad error responses when using the Echo middleware

    • The invoice response contains a 200 OK status code instead of 402 Payment Required
    • All error responses wrap the error message in JSON instead of just using the error message as text, as the other middlewares do. It should be the same for all middlewares, and it should be the text directly.
    bug 
    opened by philippgille 0
  • Performance decreases when using Lightning Charge and the amount of invoices increases

    Performance decreases when using Lightning Charge and the amount of invoices increases

    As mentioned in the v0.5.0 release notes, the ln.charge implementation of the wall.LNclient interface currently becomes slower when the amount of invoices in the Lightning Charge server increases.

    The reason is that ln-paywall currently uses the payment hash (a.k.a. preimage hash) of an invoice as ID, which works fine with lnd (and would also work with eclair). But Lightning Charge uses its own randomly generated IDs, so instead of fetching the specific ID we need, we fetch all IDs and filter out the one we're looking for by comparing the preimage hashes.

    The solution is to add the implementation specific ID as field to the wall.invoiceMetaData so it can be stored, and when a client sends the final request we can still use the preimage hash to fetch the metadata from the storage, but then use the ID within that data to make the lookup on Lightning Charge.

    This leads to the ID and the preimage hash fields being the same when using lnd. We could omit one of the fields and just use one of them, but this could also lead to confusion later.

    bug 
    opened by philippgille 0
  • Fix a client can cheat with using the wrong preimage for a request

    Fix a client can cheat with using the wrong preimage for a request

    • Previously a client just had to send any preimage that corresponds to a settled invoice in the LN node, without the invoice having to originate from the middleware, or from the same endpoint as used in the current request. So he could pay cheap invoices and use expensive endpoints for example.
    • The fix required storing metadata in the DB, e.g. the HTTP method and URL path, while being backward compatible and not send those data encrypted as token in the first response, requiring the same token and decrypting and using the values during the second request
    • Both modes are interesting and have their pros and cons, so evaluate supporting both in the future
    • Storing the metadata required changing the wall.StorageClient interface and its implementations in the storage package

    Closes #16

    opened by philippgille 0
  • Add license scan report and status

    Add license scan report and status

    Your FOSSA integration was successful! Attached in this PR is a badge and license report to track scan status in your README.

    Below are docs for integrating FOSSA license checks into your CI:

    opened by fossabot 1
  • Make client fully compatible with standard http.Client

    Make client fully compatible with standard http.Client

    Currently pay.Client only implements a subset of the http.Client's methods. I think it should be fully compatible though.

    Check out gentlemen for creating HTTP clients with middleware.

    enhancement 
    opened by philippgille 0
  • Store gobs as alternative to JSON

    Store gobs as alternative to JSON

    Currently the storage implementations all marshal and unmarshal to/from JSON. For example, a wall.invoiceMetaData object is first marshalled to JSON and then the resulting string is stored as value in Redis.

    JSON is nice because when problems occur (e.g. a customer says his HTTP client sent the correct X-Preimage header but the web service responded with an error "Corresponding invoice not found" or something similar), you can just check the storage and have a look at the stored data, easily seeing what's in there without having to decode anything. This might be harder for the Go Map (it's only visible / only exists within the running web service) and the bbolt DB (file is locked while in use), but easier for Redis and future storages like etcd and Consul, where even some web dashboards for exploring the storage contents exist.

    The downside of JSON though is that it's verbose. A binary format can be much more compact and thus require less storage.

    In Go, there are "gobs". See:

    • https://godoc.org/encoding/gob
    • https://blog.golang.org/gobs-of-data

    Before implementing this, we should first benchmark if it makes sense at all for the limited types of data we store (currently only wall.invoiceMetaData). A 50% reduction in storage would be nice, or maybe 30% is enough?

    Also be aware that when storing gobs, other programming languages can't deal with the data! For example when a customer uses one lnd instance, but two web services with one using ln-paywall and the other using a compatible Java middleware, and he wants to prevent web service clients from cheating by reusing preimages. Cheating example: Send first request to the Go web service, pay the invoice, send final request with preimage to Go web service, then send another request immediately with the same preimage to the Java web service. If both web services would have separate storage mechanisms the client could cheat that way. So a common storage must be used, like Redis for example. But when the stored value in Redis is a gob, the Java middleware can't read it. So:

    1. Using gobs instead of JSON must be optional, off by default
    2. This downside must be mentioned in the comments for the respective option (probably in the storage implementation's specific options object)
    enhancement 
    opened by philippgille 0
  • Make the middleware compatible with paypercall clients

    Make the middleware compatible with paypercall clients

    As mentioned in https://github.com/philippgille/ln-paywall/issues/16#issuecomment-423765859, ln-paywall stores invoice metadata in the storage, so it doesn't require the X-Token that paypercall requires. The token in paypercall is used to not only include the invoice ID, but also store the metadata (HTTP method, URL path) in the token, send it to the client, then the client has to include it in the final request so the middleware can read the metadata from the token again and verify it matches the method + path of the current request, so the client can't cheat.

    So while ln-paywall doesn't require it, it would be nice to be compatible with paypercall clients. Although I'm not aware of any client-side libraries (other than our own ln-paywall client, which will gain paypercall compatibility with #23), this doesn't mean no client-side code exists (could be just plain HTTP requests), and also it would be nice to offer this compatibility anyway.

    So: After #25 is implemented, after which the middleware will accept not only the preimage of a payment, but also the invoice ID, this invoice ID can just be sent as X-Token in the response to the initial request.

    I don't think this should be the default though. So make it configurable with some new wall.MiddlewareOptions.

    enhancement 
    opened by philippgille 0
  • Delete old metadata from the storage

    Delete old metadata from the storage

    Currently the invoice metadata is stored in the DB forever.

    This isn't necessary from a company's point of view, because 1) the invoices are already stored in the LN node and 2) companies that need to keep invoices around for a couple of years need additional data anyway, so the metadata in the ln-paywall storage aren't of use here.

    And it's also not necessary from an implementation point of view (since #24), because 1) LN invoices expire after some time (can be configured when creating the invoice), so when an invoice isn't paid until its expiry, the metadata is of no use anymore, and 2) due to the final request now only working when the DB has a metadata entry about the corresponding initial invoice request, cheating with reusing preimages that aren't in the storage doesn't work.

    The two cases in detail:

    • Invoice request is sent, metadata is created. The invoice expires after 1 hour (default in the LN protocol standard, see BOLT 11.
      • If the client doesn't pay within 1 hour, we can throw away the metadata anyway, because the client is technically not able to pay the invoice later (due to invoice expiry).
      • If the client does pay within 1 hour, we should give him some time to send the final request, but that shouldn't be unlimited. Considering the programmatic nature of HTTP requests, a shorter expiry might make sense (invoice payment is often done by humans, with wallet software which might require some channel syncing first etc.), but 1 hour might be fine as well. This needs to be configurable.
    • Invoice request is sent, metadata created, final request sent, metadata marked as "used", so everything is done. Until #24 the preimage needed to be kept around in storage, because otherwise a client could just use any preimage that corresponds to an invoice in the LN node and the middleware would have accepted it, but now, if a request contains a preimage, which is not in the storage, it's rejected immediately! BUT the error message might confuse clients that accidentally reuse a preimage in a second request. So for usability reasons the metadata should be kept around for a bit as well. This expiry should not start from the invoice creation, but the use (the final request).

    So:

    • Unused metadata should be kept for 1 hour (configurable) after invoice creation, to give the client time to send the final request after payment
    • Used metadata should be kept for 1 hour (configurable) after usage, to give the client proper error messages when reusing a preimage
    enhancement 
    opened by philippgille 0
  • Accept invoice ID in request header as alternative to preimage

    Accept invoice ID in request header as alternative to preimage

    So far the middleware required the preimage as payment proof in the second request.

    But since PR #24 invoice metadata is stored in the DB, with the invoice ID being used as the key, so now we could also just accept an invoice ID and look up the status in the DB or check the settlement on the LN node.

    This would make it much easier to implement clients that don't have access to the preimage. For example: Let's say the API is used on a website, but without automated payments via an LN node operated by the people running the website, and instead the website shows the user a QR code so he can pay for the API usage. Up until now the website had to ask for the preimage. This is an extra step in itself, but even worse, if the user paid via mobile wallet, but browsed the website via desktop PC, he now had to get the preimage from his smartphone to the PC just to proof that he made the payment. When the invoice ID is enough, the user doesn't have to input anything. The website can decode the LN invoice and take the invoice ID, show the user the QR code and a button "next"/"continue" or "paid", and then the website can just send the request with the invoice ID.

    One example of such a website is https://lightning.ws, where the deployed APIs have a "Try out" section where the user has to do exactly the steps mentioned above.

    enhancement 
    opened by philippgille 0
Releases(v0.5.2)
  • v0.5.2(Oct 7, 2018)

    • Fixed: When using the Echo middleware the invoice response status code was 200 OK instead of 402 Payment Required (issue #30)
    • Fixed: When using the Echo middleware error responses (including the invoice) were wrapped in JSON instead of just text (issue #30)
    • Fixed: GoDoc for storage.NewBoltClient(...) contained usage suggestions that would lead to the possibility of clients cheating with reusing preimages
    Source code(tar.gz)
    Source code(zip)
  • v0.5.1(Oct 2, 2018)

    • Fixed: Performance decreased when using Lightning Charge and the amount of invoices in the Lightning Charge server increased (issue #28)
    • Fixed: Since the introduction of the ln.Invoice struct the whole struct was logged instead of just the invoice string

    Breaking changes

    Note: The following breaking changes don't affect normal users of the package, but only those who use their own implementations of our interfaces.

    • Changed: The struct ln.Invoice now has a field ImplDepID string which is required by the middlewares. It's an LN node implementation dependent ID (e.g. payment hash for lnd, some random string for Lightning Charge). (Required for issue #28.)
    • Changed: wall.LNclient now requires the method CheckInvoice(string) (bool, error) to accept the LN node implementation dependent ID instead of the preimage hash as parameter. (Required for issue #28.)
    Source code(tar.gz)
    Source code(zip)
  • v0.5.0(Sep 23, 2018)

    • Added: Support for c-lightning with Lightning Charge (issue #6)
      • Note: The current implementation's performance decreases with the amount of invoices in the Lightning Charge server. This will be fixed in an upcoming release.
    • Added: Package pay (issue #20)
      • Interface pay.LNclient - Abstraction of a Lightning Network node client for paying LN invoices. Enables developers to write their own implementations if the provided ones aren't enough.
      • Struct pay.Client - Replacement for a standard Go http.Client
        • Factory function NewClient(httpClient *http.Client, lnClient LNclient) Client - httpClient can be passed as nil, leading to http.DefaultClient being used
        • Method Do(req *http.Request) (*http.Response, error) - Meant to be used as equivalent to the same Go http.Client method, but handles the Lightning Network payment in the background.
        • Method Get(url string) (*http.Response, error) - A convenience method for the Do(...) method, also an equivalent to the same Go http.Client method (regarding its usage)
      • Example client in examples/client/main.go
      • Note: Currently only ln.LNDclient can be used in the client, because Lightning Charge doesn't support sending payments (and maybe never will)

    • Added: Method Pay(invoice string) (string, error) for ln.LNDclient - Implements the new pay.LNclient interface, so that the LNDclient can be used as parameter in the pay.NewClient(...) function. (Issue #20)
    • Fixed: A client could cheat in multiple ways, for example use a preimage for a request to endpoint A while the invoice was for endpoint B, with B being cheaper than A. Or if the LN node is used for other purposes as well, a client could send any preimage that might be for a totally different invoice, not related to the API at all. (Issue #16)
    • Fixed: Some info logs were logged to stderr instead of stdout

    Breaking changes

    • Changed: The preimage in the X-Preimage header must now be hex encoded instead of Base64 encoded. The hex encoded representation is the typical representation, as used by "lncli listpayments", Eclair on Android and bolt11 payment request decoders like https://lndecode.com. Base64 was used previously because "lncli listinvoices" uses that encoding. (Issue #8)
    • Changed: Interface wall.StorageClient and thus all its implementations in the storage package were significantly changed. The methods are now completely independent of any ln-paywall specifics, with Set(...) and Get(...) just setting and retrieving any arbitrary interface{} to/from the storage. (Required for issue #16.)
    • Changed: The method GenerateInvoice(int64, string) (string, error) in the interface wall.LNclient was changed to return a ln.Invoice object, which makes it much easier to access the invoice ID (a.k.a. preimage hash, a.k.a. payment hash), instead of having to decode the invoice. (Useful for issue #16, in which the invoice ID is required as key in the storage.)
    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(Sep 3, 2018)

    Warning: This release contains a lot of renamings and refactorings, so your code will most definitely break. But it paves the way to upcoming features and makes some things easier, like automated testing.

    • Added: Package-level documentation
    • Improved: In case of an invalid preimage the error response is much more detailed now. It differentiates between several reasons why the preimage is invalid. Additionally more cases of invalid requests are detected now, so a proper 400 Bad Request is returned instead of a 500 Internal Server Error. (Issue #11)
    • Improved: Increased performance when creating multiple middleware instances, because the LN client implementation can now be passed into the middleware factory function and be reused across multiple middleware instances. Previously the LN client was created internally, and a new instance was created with every middleware instance.
      • Not measured, but probably a bit lower memory consumption and a bit less traffic. Probably not much regarding speed.
    • Fixed: Wrong spelling in an error message

    Breaking changes

    • Changed: Renamed package from pay to wall - this enables us to create a package called pay for client-side payments to the paywall in the future
    • Changed: Moved all storage implementations to the new package storage
    • Changed: Moved LNDoptions and DefaultLNDoptions to the from the wall (former pay) package to the ln package
      • This leads to the same kind of separation and loose coupling as with the storages
    • Changed: All middleware factory functions now take a LNclient as second parameter instead of LNDoptions
      • This also leads to the same kind of separation and loose coupling as with the storages
      • In addition it enables proper mocking of the LN client for tests (preparation for issue #10)
      • As well as own implementations of LN clients (preparation for issue #6)
    Source code(tar.gz)
    Source code(zip)
  • v0.3.0(Aug 12, 2018)

    • Added: pay.NewEchoMiddleware(...) - A middleware factory function for Echo (issue #2)
    • Added: Bolt DB client (issue #3)
      • Struct pay.BoltClient - Implements the StorageClient interface
      • Factory function NewBoltClient(...)
      • Struct pay.BoltOptions - Options for the BoltClient
      • Var pay.DefaultBoltOptions - a BoltOptions object with default values
    • Added: pay.LNclient - An abstraction of a client that connects to a Lightning Network node implementation (like lnd, c-lightning and eclair)
      • Implemented for issue #4, but will be useful for issue #6 as well
    • Added: ln.LNDclient - Implements the pay.LNclient interface (issue #4)
      • Factory function ln.NewLNDclient(...)
    • Improved: Increased middleware performance by reusing the gRPC connection to the lnd backend (issue #4)
      • With the same setup (local Gin web service, pay.GoMap as storage client, remote lnd, same hardware) it took about 100ms per request before, and takes about 25ms per request now. Measured from the arrival of the initial request until the sending of the response with the Lightning invoice (as logged by Gin).
    • Fixed: Success log message mentioned "HandlerFunc" in all middlewares despite it not always being a HandlerFunc
    • Fixed: A wrong HTTP status code was used in responses when an internal error occurred (400 Bad Request instead of 500 Internal Server Error)

    Breaking changes

    Package pay:

    • Changed: Renamed pay.InvoiceOptions.Amount to pay.InvoiceOptions.Price to avoid misunderstandings

    Package ln (none of these changes should affect anyone, because this package is meant to be used only internally):

    • Removed: ln.NewLightningClient(...) - Not required anymore after adding the much more usable ln.NewLNDclient(...).
    • Changed: ln.GenerateInvoice(...) from being a function to being a method of ln.LNDclient and removed all lnd connection-related parameters which are part of the LNDclient. (issue #4)
    • Changed ln.CheckInvoice(...) from being a function to being a method of ln.LNDclient and removed all lnd connection-related parameters which are part of the LNDclient. (issue #4)
    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(Jul 29, 2018)

    • Added: Interface pay.StorageClient - an abstraction for multiple storage clients, which allows you to write your own storage client for storing the preimages that have already been used as payment proof in a request (issue #1)
      • Methods WasUsed(string) (bool, error) and SetUsed(string) error
    • Added: Struct pay.RedisClient - implements the StorageClient interface (issue #1)
      • Factory function NewRedisClient(...)
    • Added: Var pay.DefaultRedisOptions - a RedisOptions object with default values
    • Added: Struct pay.GoMap - implements the StorageClient interface (issue #1)
      • Factory function NewGoMap()
    • Improved: Increased middleware performance and decreased load on the connected lnd when invalid requests with the x-preimage header are received (invalid because the preimage was already used) - Instead of first getting a corresponding invoice for a preimage from the lnd and then checking if the preimage was used already, the order of these operations was switched, because then, if the preimage was already used, no request to lnd needs to be made anymore.
    • Improved: All fields of the struct pay.RedisOptions are now optional

    Breaking changes

    Package pay:

    • Changed: pay.NewHandlerFuncMiddleware(...), pay.NewHandlerMiddleware(...) and pay.NewGinMiddleware(...) now take a ln.StorageClient instead of a *redis.Client as parameter (issue #1)

    Package ln (none of these changes should affect anyone, because this package is meant to be used only internally):

    • Changed: ln.CheckPreimage(...) was renamed to ln.CheckInvoice(...) and doesn't check the storage anymore. The ln methods are supposed to just handle lightning related things and nothing else.
    • Removed: Package lnrpc - Instead of using our own generated lnd gRPC Go file, import the one from Lightning Labs.
    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Jul 2, 2018)

Owner
Philipp Gillé
Software engineer, progressive, cosmopolitan, globalist, futurist, technology maximalist - interested in #technology #innovation #blockchain #bitcoin #lightning
Philipp Gillé
Fault injection library in Go using standard http middleware

Fault The fault package provides go http middleware that makes it easy to inject faults into your service. Use the fault package to reject incoming re

GitHub 459 Jul 29, 2022
Dead simple rate limit middleware for Go.

Limiter Dead simple rate limit middleware for Go. Simple API "Store" approach for backend Redis support (but not tied too) Middlewares: HTTP, FastHTTP

Ulule 1.6k Aug 8, 2022
Simple middleware to rate-limit HTTP requests.

Tollbooth This is a generic middleware to rate-limit HTTP requests. NOTE 1: This library is considered finished. NOTE 2: Major version changes are bac

Didip Kerabat 2.3k Aug 2, 2022
A Golang Middleware to handle X-Forwarded-For Header

X-Forwarded-For middleware fo Go Package xff is a net/http middleware/handler to parse Forwarded HTTP Extension in Golang. Example usage Install xff:

Sebest 90 Jul 10, 2022
Stash is a locally hosted web-based app written in Go which organizes and serves your porn.

Stash is a locally hosted web-based app written in Go which organizes and serves your porn.

null 2.2k Aug 4, 2022
Go (golang) library for creating and consuming HTTP Server-Timing headers

HTTP Server-Timing for Go This is a library including middleware for using HTTP Server-Timing with Go. This header allows a server to send timing info

Mitchell Hashimoto 839 Jul 26, 2022
Redcon is a custom Redis server framework for Go that is fast and simple to use.

Redcon is a custom Redis server framework for Go that is fast and simple to use. The reason for this library it to give an efficient server front-end for the BuntDB and Tile38 projects.

Josh Baker 1.8k Aug 1, 2022
A simple and lightweight encrypted password manager written in Go.

A simple and lightweight encrypted password manager written in Go.

null 32 Jun 16, 2022
Remark42 is a self-hosted, lightweight, and simple comment engine

Remark42 is a self-hosted, lightweight, and simple (yet functional) comment engine, which doesn't spy on users. It can be embedded into blogs, articles or any other place where readers add comments.

Umputun 3.9k Aug 8, 2022
👄 The most accurate natural language detection library in the Go ecosystem, suitable for long and short text alike

Its task is simple: It tells you which language some provided textual data is written in. This is very useful as a preprocessing step for linguistic data in natural language processing applications such as text classification and spell checking. Other use cases, for instance, might include routing e-mails to the right geographically located customer service department, based on the e-mails' languages.

Peter M. Stahl 688 Jul 28, 2022
Enforcing per team quota (sum of used resources across all their namespaces) and delegating the per namespace quota to users.

Quota Operator Enforcing per team quota (sum of used resources across all their namespaces) and delegating the per namespace quota to users. Instructi

Snapp Cab Incubators 17 Aug 4, 2022
Go implementation of a vanity attempt to generate Bitcoin private keys and subsequently checking whether the corresponding Bitcoin address has a non-zero balance.

vanity-BTC-miner Go implementation of a vanity attempt to generate Bitcoin private keys and subsequently checking whether the corresponding Bitcoin ad

Lih Ingabo 1 Jun 3, 2022
A proof-of-concept Bitcoin client that treats Bitcoin with the contempt it deserves

Democracy A proof-of-concept Bitcoin client that treats Bitcoin with the contempt it deserves. Bitcoin offers no inbuilt democracy. One can either vot

Josh Deprez 2 Jul 19, 2022
This is the basis of the bot for viewing information on the crp.is exchange in a telegram.

crye_go_bot An example of a telegram bot for working with the crp.is exchange Usage Create config.json to test bot operation Later Test the bot by cre

null 0 Jan 15, 2022
⚡ 🖥️ 👾 Host your own Lightning Address on LND

⚡ ??️ ?? Host your own Lightning Address on LND Lighting Wallets like BlueWallet, Blixt and many more allow us to send sats to Lighting Addresses like

Heebs 8 Jun 12, 2022
Goget will send a http request, and show the request time, status, response, and save response to a file

Goget will send a http request, and show the request time, status, response, and save response to a file

LAZPbanahaker 2 Feb 9, 2022
Header Block is a middleware plugin for Traefik to block request and response headers which regex matched by their name and/or value

Header Block is a middleware plugin for Traefik to block request and response headers which regex matched by their name and/or value Conf

null 3 May 24, 2022
Request: a HTTP request library for Go with interfaces and mocks for unit tests

Requester Request is a HTTP request library for Go with interfaces and mocks for

Doğukan Aydoğdu 1 Jan 10, 2022
Validate Golang request data with simple rules. Highly inspired by Laravel's request validation.

Validate golang request data with simple rules. Highly inspired by Laravel's request validation. Installation Install the package using $ go get githu

Saddam H 1.1k Aug 6, 2022
github-actions-merger is github actions that merges pull request with commit message including pull request labels.

github-actions-merger github-actions-merger is github actions that merges pull request with commit message including pull request labels. Usage Write

ABEMA 6 Jun 14, 2022
Add request id to a request's context

RequestID ?? This is a very simple piece of middleware for adding request/correlation IDs to the context of a http request. By default, this module wi

Jamie Aitken 0 Dec 4, 2021
gorilla/csrf provides Cross Site Request Forgery (CSRF) prevention middleware for Go web applications & services 🔒

gorilla/csrf gorilla/csrf is a HTTP middleware library that provides cross-site request forgery (CSRF) protection. It includes: The csrf.Protect middl

Gorilla Web Toolkit 816 Aug 1, 2022
Go http middleware handler for request coalescing

HTTP Coala NOTE: a new and improved implementation is available at https://github.com/go-chi/stampede Just a little bit of performance enhancing middl

go-chi 128 Apr 3, 2022
gorilla/csrf provides Cross Site Request Forgery (CSRF) prevention middleware for Go web applications & services 🔒

gorilla/csrf gorilla/csrf is a HTTP middleware library that provides cross-site request forgery (CSRF) protection. It includes: The csrf.Protect middl

Gorilla Web Toolkit 816 Aug 1, 2022
Just a playground with some interesting concepts like pipelines aka middleware, handleFuncs, request validations etc. Check it out.

Pipeline a.k.a middleware in Go Just a playground with some interesting concepts like pipelines aka middleware, handleFuncs, request validations etc.

null 0 Dec 9, 2021
Gin-errorhandling - Gin Error Handling Middleware is a middleware for the popular Gin framework

Gin Error Handling Middleware Gin Error Handling Middleware is a middleware for

Joseph Woodward 8 Jul 25, 2022
Fortio load testing library, command line tool, advanced echo server and web UI in go (golang). Allows to specify a set query-per-second load and record latency histograms and other useful stats.

Fortio Fortio (Φορτίο) started as, and is, Istio's load testing tool and now graduated to be its own project. Fortio is also used by, among others, Me

Fortio (Φορτίο) 2.6k Aug 9, 2022
A lightning fast image processing and resizing library for Go

govips A lightning fast image processing and resizing library for Go This package wraps the core functionality of libvips image processing library by

David Byttow 731 Aug 8, 2022
lightning - forward messages between a qq group and a telegram group

lightning The purpose of this project is to forward messages between a qq group and a telegram group. Getting Started Clone this project: git clone ht

方泓睿 6 Dec 15, 2021