A http service to verify request and bounce them according to decisions made by CrowdSec.

Overview

GitHub GitHub go.mod Go version Go Report Card GitHub Workflow Status GitHub tag (latest SemVer) Docker Image Size (latest semver)

traefik-crowdsec-bouncer

A http service to verify request and bounce them according to decisions made by CrowdSec.

Description

This repository aim to implement a CrowdSec bouncer for the router Traefik to block malicious IP to access your services. For this it leverages Traefik v2 ForwardAuth middleware and query CrowdSec with client IP. If the client IP is on ban list, it will get a http code 403 response. Otherwise, request will continue as usual.

Demo

Prerequisites

Docker and Docker-compose installed.
You can use the docker-compose in the examples' folder as a starting point. Through traefik it exposes the whoami countainer on port 80, with the bouncer accepting and rejecting client IP.
Launch your all services except the bouncer with the follow commands:

git clone https://github.com/fbonalair/traefik-crowdsec-bouncer.git
cd examples
docker-compose up -d traefik crowdsec whoami 

Procedure

  1. Get an bouncer API key from CrowdSec with command docker exec crowdsec-example cscli bouncers add traefik-bouncer
  2. Copy the API key printed. You WON'T be able the get it again.
  3. Past this key as the value for bouncer environment variable CROWDSEC_BOUNCER_API_KEY, instead of "MyApiKey"
  4. Start bouncer in attach mode with docker-compose up bouncer
  5. Start a browser and visit http://localhost/. You will see the container whoami page, copy your IP address from X-Real-Ip line (i.e. 192.168.128.1).
    In your console, you will see lines showing your authorized request (i.e. "status":200).
  6. In another console, ban your IP with command docker exec crowdsec-example cscli decisions add --ip 192.168.128.1, modify the IP with your address.
  7. Visit http://localhost/ again, in your browser you will see "Forbidden" since this time since you've been banned. Though the console you will see "status":403.
  8. Unban yourself with docker exec crowdsec-example cscli decisions delete --ip 192.168.128.1
  9. Visit http://localhost/ one last time, you will have access to the container whoami.

Enjoy!

Usage

For now, this web service is mainly fought to be used as a container.

Prerequisites

You should have Traefik v2 and a CrowdSec instance running.
The container is available on docker as image fbonalair/traefik-crowdsec-bouncer. Host it as you see fit, though it must have access to CrowdSec and be accessible by Traefik.
Follow traefik v2 ForwardAuth middleware documentation to create a forwardAuth middle pointing to your bouncer host.
Generate a bouncer API key following CrowdSec documentation

Configuration

The webservice configuration is made via environment variables:

  • CROWDSEC_BOUNCER_API_KEY - CrowdSec bouncer API key required to be authorized to request local API (required)`
  • CROWDSEC_AGENT_HOST - Host and port of CrowdSec agent. i.e crowdsec-agent:8080 (required)`
  • CROWDSEC_BOUNCER_SCHEME - Scheme to query CrowdSec agent. Expected value: http, https. Default to http`
  • PORT - Change listening port of web server. Default listen on 8080
  • GIN_MODE - By default, run app in "debug" mode. Set it to "release" in production

Exposed routes

The webservice exposes 3 routes:

  • /api/v1/forwardAuth - Main route to be used by Traefik: query CrowdSec agent with the header X-Real-Ip as client IP`
  • /api/v1/ping - Simple health route that respond pong with http 200`
  • /api/v1/healthz - Another health route that query CrowdSec agent with localhost (127.0.0.1)`

Contribution

TBD

Issues
  • Bouncer doesn't correctly process X-Forwarded-For headers

    Bouncer doesn't correctly process X-Forwarded-For headers

    crowdsec-bouncer-traefik  | 2022-01-12T00:11:31Z DBG No decision for IP "192.168.0.13". Accepting
    crowdsec-bouncer-traefik  | {"level":"info","status":200,"method":"GET","path":"/api/v1/forwardAuth","ip":"192.168.0.13","latency":2.450771,"user_agent":"Gatus/1.0","time":"2022-01-12T00:11:31Z","message":"Request"}
    crowdsec-bouncer-traefik  | 2022-01-12T00:11:31Z DBG No decision for IP "192.168.0.13". Accepting
    crowdsec-bouncer-traefik  | {"level":"info","status":200,"method":"GET","path":"/api/v1/forwardAuth","ip":"192.168.0.13","latency":2.440972,"user_agent":"Gatus/1.0","time":"2022-01-12T00:11:31Z","message":"Request"}
    crowdsec-bouncer-traefik  | 2022-01-12T00:11:32Z DBG No decision for IP "172.20.6.1". Accepting
    crowdsec-bouncer-traefik  | {"level":"info","status":200,"method":"GET","path":"/api/v1/forwardAuth","ip":"172.20.6.1","latency":2.334519,"user_agent":"Prometheus/2.32.1","time":"2022-01-12T00:11:32Z","message":"Request"}
    crowdsec-bouncer-traefik  | 2022-01-12T00:11:34Z DBG No decision for IP "172.70.34.108". Accepting
    crowdsec-bouncer-traefik  | {"level":"info","status":200,"method":"GET","path":"/api/v1/forwardAuth","ip":"44.200.29.26","latency":2.456313,"user_agent":"axios/0.21.4","time":"2022-01-12T00:11:34Z","message":"Request"}
    

    As you can see the initial requests are internal addresses and the DBG lookup matches the subsequent request, however, the last request in the list is doing a Decision lookup for the last hop address (Cloudflare in this instance - 172.70.34.108) rather than the real address (44.200.29.26) and is allowing it even if it's banned.

    In the specific instance:

    crowdsec-bouncer-traefik  | 2022-01-12T00:11:54Z DBG No decision for IP "162.158.183.237". Accepting
    crowdsec-bouncer-traefik  | {"level":"info","status":200,"method":"GET","path":"/api/v1/forwardAuth","ip":"157.90.177.214","latency":2.464756,"user_agent":"Mozilla/5.0 (compatible; BLEXBot/1.0; +http://webmeup-crawler.com/)","time":"2022-01-12T00:11:54Z","message":"Request"}
    
    +---------+----------+-------------------+-----------------------------------+--------+---------+--------------------------------+--------+--------------------+----------+
    |   ID    |  SOURCE  |    SCOPE:VALUE    |              REASON               | ACTION | COUNTRY |               AS               | EVENTS |     EXPIRATION     | ALERT ID |
    +---------+----------+-------------------+-----------------------------------+--------+---------+--------------------------------+--------+--------------------+----------+
    | 1010386 | crowdsec | Ip:157.90.177.214 | crowdsecurity/http-bad-user-agent | ban    | US      |                             0  |      2 | 3h38m42.992170366s |     2623 |
    

    157.90.177.214 is banned but the bouncer allows it because the lookup is performed against 162.158.183.237 (Cloudflare) instead.

    opened by thespad 27
  • Bouncer can't connect to CrowdSec instance

    Bouncer can't connect to CrowdSec instance

    Hi!

    Face with strange behaviour, I have an several same install of crowdsec and traefik bouncer in docker, and right now I install this stuff to my vps, but, not understand what is wrong, maybe someone can help and resolve it, traefik bouncer can't connect to the crowdsec instance, 'coz ip address of container in not in bouncers list, and I can't understand whats is wrong in my compose or my settings of current stack.

    Here is an screen of bouncers list: image

    Here is an my containers: image

    And my stack:

    version: '3'
    
    networks:
      proxy:
        external: true
    
    volumes:
      config:
        driver: local
      db:
        driver: local
    
    services:
    
      crowdsec:
        image: crowdsecurity/crowdsec:latest
        container_name: crowdsec
        networks:
          - proxy
        environment:
          - TZ=Europe/Kiev
          - COLLECTIONS="crowdsecurity/linux crowdsecurity/traefik"
          - GID=${GID-1000}
        volumes:
          - ${DOCKER_HOST_PATH}/crowdsec/config/acquis.yaml:/etc/crowdsec/acquis.yaml
          - ${DOCKER_HOST_PATH}/crowdsec/config/profiles.yaml:/etc/crowdsec/profiles.yaml
          - ${DOCKER_HOST_PATH}/crowdsec/notifications/http.yaml:/etc/crowdsec/notifications/http.yaml
          - db:/var/lib/crowdsec/data/
          - config:/etc/crowdsec/
          # Traefik's logs read-only
          - ${DOCKER_HOST_PATH}/traefik/logs:/var/log/traefik:ro
          # Authelia's logs read-only
          #- ${DOCKER_HOST_PATH}/authelia/authelia.log:/var/log/authelia.log:ro
        restart: unless-stopped
        logging:
          driver: "json-file"
          options:
            max-size: "35m"
          
      traefik-crowdsec-bouncer:
        image: docker.io/fbonalair/traefik-crowdsec-bouncer:latest
        container_name: traefik-crowdsec-bouncer
        networks:
          - proxy
        depends_on:
          - crowdsec
        environment:
          - TZ=Europe/Kiev
          - CROWDSEC_BOUNCER_API_KEY=${BOUNCER_TRAEFIK_API_KEY}
          - CROWDSEC_AGENT_HOST=crowdsec:8080
          - CROWDSEC_BOUNCER_LOG_LEVEL=0
        restart: unless-stopped
        logging:
          driver: "json-file"
          options:
            max-size: "10m"
    

    The only difference from my previous stacks: I added telegram alerts, and my internal docker network is 192.168.135.0/24 - and that's all differents.

    opened by SAOPP 13
  • Bouncer can't send ban request to crowdsec

    Bouncer can't send ban request to crowdsec

    I honestly don't know if this is bouncer issue or crowdsec. I tried to ddos my own website and check if bouncer block it. I saw some requests from bouncer but show error below. my logs file:

    2022-03-02T02:45:07Z WRN An error occurred while checking IP "" error="Get \"http://crowdsec:8080/v1/decisions?type=ban&ip=MYIP\": context deadline exceeded (Client.Timeout exceeded while awaiting headers)"
    
    opened by phamleduy04 5
  • Working alongside thomseddon/traefik-forward-auth:2

    Working alongside thomseddon/traefik-forward-auth:2

    Hi,

    I am trying to get this to work alongside thomseddon/traefik-forward-auth:2 to add an additional layer of forward-auth but I cant seem to get it working.

    Traefik version 2.6.1

    Traefik args:

          - "[email protected]"
          - "[email protected]"
    

    docker-compose.yaml

    version: '3.8'
    services:
      crowdsec:
        image: crowdsecurity/crowdsec:latest
        environment:
          GID: "${GID-1000}"
          COLLECTIONS: "crowdsecurity/linux crowdsecurity/traefik"
        volumes:
          - ./config/acquis.yaml:/etc/crowdsec/acquis.yaml
          - crowdsec-db:/var/lib/crowdsec/data/
          - crowdsec-config:/etc/crowdsec/
          - /ztemp/logs/traefik:/var/log/traefik/:ro
        networks:
          - traefik_public
        restart: unless-stopped
        deploy:
          labels:
            - traefik.enable=false
    
      bouncer-traefik:
        image: docker.io/fbonalair/traefik-crowdsec-bouncer:latest
        container_name: bouncer-traefik
        environment:
          CROWDSEC_BOUNCER_API_KEY: <my-api-key>
          CROWDSEC_AGENT_HOST: crowdsec:8080
        networks:
          - traefik_public
        depends_on:
          - crowdsec
        restart: unless-stopped
        deploy:
          labels:
            - "traefik.enable=true"
            - "traefik.http.middlewares.crowdsec-bouncer.forwardauth.address=http://bouncer-traefik:8080/api/v1/forwardAuth"
            - "traefik.http.middlewares.crowdsec-bouncer.forwardauth.trustForwardHeader=true"
            - "traefik.http.services.crowdsec-bouncer.loadbalancer.server.port=8080"
    
    networks:
      traefik_public:
        external: true
    volumes:
      crowdsec-db:
    

    I am seeing the middleware in the traefik dash: image

    And if I look at my routers, both the foward-auth and the bouncer is associated: image

    image image

    However the request from blocked IPs DOES NOT get forbidden.

    Oddly, I also have a static service+router defined for a bare metal box outside docker and that is now also picking up the bouncer middleware and requests from blocked clients IS being blocked.

    I have tried removing the other foward-auth middleware from one of my services so its only got the bouncer associated and its still not rejecting banned clients:

    image

    Here are some logs from the bouncer:

    {"level":"info","status":200,"method":"GET","path":"/api/v1/forwardAuth","ip":"172.16.200.3","latency":45.521328,"user_agent":"Mozilla/5.0 (Linux; Android 12; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.87 Mobile Safari/537.36","time":"2022-02-15T12:26:43Z","message":"Request"}
    {"level":"info","status":200,"method":"GET","path":"/api/v1/forwardAuth","ip":"172.16.200.3","latency":77.551311,"user_agent":"Mozilla/5.0 (Linux; Android 12; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.87 Mobile Safari/537.36","time":"2022-02-15T12:26:43Z","message":"Request"}
    {"level":"info","status":200,"method":"GET","path":"/api/v1/forwardAuth","ip":"172.16.200.3","latency":32.077496,"user_agent":"Mozilla/5.0 (Linux; Android 12; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.87 Mobile Safari/537.36","time":"2022-02-15T12:26:43Z","message":"Request"}
    {"level":"info","status":200,"method":"GET","path":"/api/v1/forwardAuth","ip":"172.16.200.3","latency":12.25493,"user_agent":"Mozilla/5.0 (Linux; Android 12; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.87 Mobile Safari/537.36","time":"2022-02-15T12:26:43Z","message":"Request"}
    {"level":"info","status":200,"method":"GET","path":"/api/v1/forwardAuth","ip":"172.16.200.3","latency":26.94213,"user_agent":"Mozilla/5.0 (Linux; Android 12; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.87 Mobile Safari/537.36","time":"2022-02-15T12:26:43Z","message":"Request"}
    {"level":"info","status":200,"method":"GET","path":"/api/v1/forwardAuth","ip":"172.16.200.3","latency":20.995469,"user_agent":"Mozilla/5.0 (Linux; Android 12; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.87 Mobile Safari/537.36","time":"2022-02-15T12:26:43Z","message":"Request"}
    {"level":"info","status":200,"method":"GET","path":"/api/v1/forwardAuth","ip":"172.16.200.3","latency":15.450635,"user_agent":"Mozilla/5.0 (Linux; Android 12; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.87 Mobile Safari/537.36","time":"2022-02-15T12:26:47Z","message":"Request"}
    {"level":"warn","status":403,"method":"GET","path":"/api/v1/forwardAuth","ip":"172.16.200.3","latency":25.430298,"user_agent":"Mozilla/5.0 (Linux; Android 12; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.87 Mobile Safari/537.36","time":"2022-02-15T12:26:51Z","message":"Request"}
    {"level":"warn","status":403,"method":"GET","path":"/api/v1/forwardAuth","ip":"172.16.200.3","latency":12.728283,"user_agent":"Mozilla/5.0 (Linux; Android 12; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.87 Mobile Safari/537.36","time":"2022-02-15T12:26:52Z","message":"Request"}
    

    The bottom two are blocks on a file provider service, the others are docker services.

    Any ideas? It's probably just a label/mis-config somewhere but I have tried loads of combinations to get to this stage.

    Thanks in advance.

    opened by jonwilliams84 4
  • Distroless image has no access to wget/curl

    Distroless image has no access to wget/curl

    Hi,

    First of all, thanks for this awesome bouncer. For which you have specified some nice health check APIs, which I was aiming to use to implement a docker HEALTHCHECK. However, because the distroless does not contain any wget or curl CMDs, it is not possible to do this.

    Can a light weight wget binary be added so that a HEALTHCHECK could properly be implemented.

    opened by rkokkelk 3
  • Fix for Trusted Proxies and use ClientID()

    Fix for Trusted Proxies and use ClientID()

    Not sure if you accept pull requests so here goes? This is related to #10

    Sets this to work correctly on ClientID() which defaults to X-Forwarded-For behind a trusted proxy. Since this should be behind traefik and traefik decides which proxies it trusts before we can keep this set as 0.0.0.0/0 but there is an option to set this with the TRUSTED_PROXIES environmental variable.

    Note that this might not be as performant as setting SetTrustedProxy(nil) and using ClientID() if you don't have proxies before Traefik. I wanted to add in some logic to set SetTrustedProxy(nil) instead if TRUSTED_PROXY wasn't set at all but my experience with go isn't that great and honestly not sure it even matters in most use cases for this bouncer but it is a potential for improvement if you want the previous functionality to stand.

    opened by pewter77 2
  • refactor: docker healthcheck to be more permissive

    refactor: docker healthcheck to be more permissive

    With the default Healthcheck, the timeout is set to strict. When using the bouncer on a node with a high load, the container runs fine but the healthcheck is not finished within 1s thus killing the container. By setting the healthcheck to a larger timeout and include some retries, the healthcheck should work fine even when executed on high load nodes.

    opened by rkokkelk 2
  • capi cant load

    capi cant load

    Hello there just installed with a little guide: https://docs.technotim.live/posts/crowdsec-traefik/

    And had the same issue as described here: https://github.com/crowdsecurity/crowdsec/issues/1324

    $ sudo cscli capi register
    WARN[08-03-2022 04:55:27 PM] can't load CAPI credentials from '/etc/crowdsec/online_api_credentials.yaml' (missing field) 
    INFO[08-03-2022 04:55:27 PM] push and pull to Central API disabled        
    FATA[08-03-2022 04:55:28 PM] api client register ('https://api.crowdsec.net/'): api register (https://api.crowdsec.net/) http 400 Bad Request : http code 400, invalid body: invalid character '\'' in string escape code: http code 400, invalid body: invalid character '\'' in string escape code
    
    

    So i am new to crowdsec but without capi detection is not possible, as i understand so this should be addressed.

    Hope this helps.

    opened by geekblog-dev 1
  • Configurable response codes?

    Configurable response codes?

    I'd like the option to have configurable response codes i.s.o. the standard 403.

    Yes, this is technically not quite right, but based on these return codes attackers could steer their search. Between 404: Nothing here, vs 403: something here but no right to access, I'd like to have any malicious query think there's no benefit in attempting a retry.

    Adding an environment variable (e.g. BAN_RESPONSE_CODE) to configure what response code should be used would enable this.

    opened by RoboMagus 1
  • Option to ignore specific traefik routers

    Option to ignore specific traefik routers

    I have a web app that is constantly queried by RSS readers and all of them are being flagged by crowdsec.

    If I use the middleware on every router except the commonly queried web-app one, then the RSS feeds would go through, although those specific IP's would still be flagged and blocked from other services that traefik serves, because all the traefik logs go to the same file.

    It would be a nice option to ignore log lines which contain a given string (perhaps router name), so those IPs aren't suspicious within crowdsec.

    opened by rwjack 1
  • RFC: X-Real-Ip Header not trustable, X-Forwarded-For more reliable

    RFC: X-Real-Ip Header not trustable, X-Forwarded-For more reliable

    https://github.com/fbonalair/traefik-crowdsec-bouncer/blob/403c736ae499c6dc2c193f87dd37d8810033f100/controler/controler.go#L116

    Dear,

    In case of an architecture with proxy-chaining (TCP, HTTP, SNAT...), the X-Real-Ip header is not trustable on Traefik. It would be great to implement an option allowing the usage of the X-Forwarded-For instead of X-Real-Ip.

    Its format:

    X-Forwarded-For: < Client IP >, < Proxy IP 1 >, < Proxy IP 2 >

    Examples of values:

    X-Forwarded-For: 192.168.10.11 X-Forwarded-For: 123.123.123.123, 172.16.1.1 X-Forwarded-For: 123.123.123.123, 172.16.1.1, 10.50.1.1 X-Forwarded-For: 123.123.123.123, 172.16.1.1, 10.50.1.1, 1.1.1.1

    So, when XFF is used, only the first IP is relevant.

    Thank you in advance.

    opened by vherrlein 1
  • Added support for docker secrets

    Added support for docker secrets

    Right now the bouncer API key needs to be hardcoded in the compose file and/or in the external .env. The current best practice is to leverage docker secrets that are not only supported in swarm mode, but also from docker compose.

    I have added a basic implementation within the RequiredEnv function, that allows the use of <environment_variable_name>+_FILE instead of <environment_variable_name>. So CROWDSEC_BOUNCER_API_KEY becomes CROWDSEC_BOUNCER_API_KEY_FILE. If said [...]_FILE variable exists the value is read from the file and returned from the RequiredEnv function.

    I'd greatly appreciate some testing since logging from config.go seems kind of impossible? Even the existing log.Fatalf() entries I never get to see in the docker logs (though the container doesn't start).

    Example docker-compose:

    version: "3.8"
    
    secrets:
      crowdsec_bouncer_api_key:
        file: /secretsPath/crowdsec_bouncer_api_key
    
    services:
      bouncer:
        build: .
        image: fbonalair/traefik-crowdsec-bouncer
        container_name: bouncer
        environment:
          CROWDSEC_BOUNCER_API_KEY_FILE: /run/secrets/crowdsec_bouncer_api_key
          CROWDSEC_AGENT_HOST: crowdsec:8123
        secrets:
          - crowdsec_bouncer_api_key
    
    opened by DennisGaida 1
  • Can this bouncer be used for other non-http services (i.e. tcp/udp)?

    Can this bouncer be used for other non-http services (i.e. tcp/udp)?

    All examples and documentation lead towards the most obvious usage, which is http/https trafic being directed to this middleware in order to sort out if the request is granted/denied later down the pipe.

    However, my question is targeted to other services with plain tcp connections (even udp): Can this middleware be used in those cases too. Could it be used, for instance, to protect incoming connections to 25565 port (minecraft) from bad actors?

    If so, how? Some examples would be great. Thanks.

    opened by jagbarcelo 1
  • bouncer is not detecting real IP address when server is exposed via cloudflare

    bouncer is not detecting real IP address when server is exposed via cloudflare

    Hi, I have my server pointing to Cloudflare and authelia is implemented for security purpose. Now when client access the locally hosted website they pass the crowdsec and comes to authelia for credential and then have access to the website. It perfect it works as expected. But looking at the logs, crowdsec bouncer points out that, IP was from cloudflare, where as my authelia instance do detect real ip address of client. It must be my configuration issue, but can you able to point out what I am doing wrong here?

    opened by dhruvinsh 2
  • Implement caching to avoid a ton of requests to crowdsec api

    Implement caching to avoid a ton of requests to crowdsec api

    Currently every request gets forwarded to crowdsec one by one and it is slow and resource intensive. In my setup I have setup mariadb additionally and calling crowdsec on every request results in a call to the db. All this can be avoided with a single json file with cached ip addresses on the bouncers side. Similar to how cloudflare bouncer is caching them. This also results in pretty big mariadb binary logs. Simple cache mechanism would save space and increase performance by having less impact on the system. File based caching (like json) would be enough, but redis would be awesome.

    opened by aleksandarmomic 4
Releases(v0.1.1)
Owner
Fabien Bonalair
Fabien Bonalair
echo-http - Echo http service

echo-http - Echo http service Responds with json-formatted echo of the incoming request and with a predefined message. Can be install directly (go get

Umputun 13 Jun 10, 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
A golang registry for global request variables.

context ?? This library is in maintenance mode. ⚠ ⚠ ⚠ Note ⚠ ⚠ ⚠ gorilla/context, having been born well before context.Context existed, does not play

Gorilla Web Toolkit 417 Jun 22, 2022
Mahi is an all-in-one HTTP service for file uploading, processing, serving, and storage.

Mahi is an all-in-one HTTP service for file uploading, processing, serving, and storage. Mahi supports chunked, resumable, and concurrent uploads. Mahi uses Libvips behind the scenes making it extremely fast and memory efficient.

Rodrigo Lessa 32 May 29, 2022
A HTTP mole service

httpmole provides a HTTP mock server that will act as a mole among your services, telling you everything http clients send to it and responding them whatever you want it to respond. Just like an actual mole.

José Carlos Chávez 130 Jul 27, 2022
HTTP/2 Apple Push Notification service (APNs) provider for Go with token-based connection

APNs Provider HTTP/2 Apple Push Notification service (APNs) provider for Go with token-based connection Example: key, err := apns.AuthKeyFromFile("Aut

Vitaly Berg 17 Apr 23, 2022
A dead simple, stupid, http service.

A dead simple, stupid, http service implemented in a complicated way just for the sake of following Go design patterns and scalability. Useful for learning and testing basic kubernetes networking. Made on an insomniac night.

Rudraksh Pareek 2 Sep 13, 2021
Link converter service converts URLs to deeplinks or deeplinks to URLs.

Link converter Link converter service converts URLs to deeplinks or deeplinks to URLs. The service responds to the incoming request and first checks w

İlker Rişvan 0 Dec 23, 2021
Composable chains of nested http.Handler instances.

chain go get github.com/codemodus/chain Package chain aids the composition of nested http.Handler instances. Nesting functions is a simple concept. I

Code Modus 64 Jan 24, 2022
Go http.Hander based middleware stack with context sharing

wrap Package wrap creates a fast and flexible middleware stack for http.Handlers. Features small; core is only 13 LOC based on http.Handler interface;

go-on - web toolkit in Go 59 Apr 5, 2022
Minimalist net/http middleware for golang

interpose Interpose is a minimalist net/http middleware framework for golang. It uses http.Handler as its core unit of functionality, minimizing compl

James Pirruccello 295 Apr 5, 2022
Add interceptors to GO http.Client

mediary Add interceptors to http.Client and you will be able to Dump request and/or response to a Log Alter your requests before they are sent or resp

Here Mobility SDK 79 Jul 6, 2022
Lightweight Middleware for net/http

MuxChain MuxChain is a small package designed to complement net/http for specifying chains of handlers. With it, you can succinctly compose layers of

Stephen Searles 209 Apr 5, 2022
Idiomatic HTTP Middleware for Golang

Negroni Notice: This is the library formerly known as github.com/codegangsta/negroni -- Github will automatically redirect requests to this repository

null 7.2k Aug 6, 2022
A tiny http middleware for Golang with added handlers for common needs.

rye A simple library to support http services. Currently, rye provides a middleware handler which can be used to chain http handlers together while pr

InVision 97 Feb 9, 2022
A collection of useful middleware for Go HTTP services & web applications 🛃

gorilla/handlers Package handlers is a collection of handlers (aka "HTTP middleware") for use with Go's net/http package (or any framework supporting

Gorilla Web Toolkit 1.4k Aug 7, 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
OpenID Connect (OIDC) http middleware for Go

Go OpenID Connect (OIDC) HTTP Middleware Introduction This is a middleware for http to make it easy to use OpenID Connect. Currently Supported framewo

Xenit AB 60 Jul 24, 2022
Hex - Expectations for HTTP handlers

Hex is a simple wrapper that extends httptest.Server with an expectation syntax, allowing you to create mock APIs using a simple and expressive DSL:

null 11 Aug 9, 2021