A feature flag solution, with only a YAML file in the backend (S3, GitHub, HTTP, local file ...), no server to install, just add a file in a central system and refer to it. 🎛️

go-feature-flag logo

🎛️ go-feature-flag Tweet

Build Status Coverage Status Sonarcloud Status License FOSSA Status
Release version GoDoc Go version Mentioned in Awesome Go

A feature flag solution, with YAML file in the backend (S3, GitHub, HTTP, local file ...).
No server to install, just add a file in a central system (HTTP, S3, GitHub, ...) and all your services will react to the changes of this file.

If you are not familiar with feature flags also called feature Toggles you can read this article of Martin Fowler that explains why this is a great pattern.
I've also wrote an article that explains why feature flags can help you to iterate quickly.

Installation

go get github.com/thomaspoignant/go-feature-flag

Quickstart

First, you need to initialize the ffclient with the location of your backend file.

err := ffclient.Init(ffclient.Config{
    PollInterval: 3,
    Retriever: &ffclient.HTTPRetriever{
        URL:    "http://example.com/test.yaml",
    },
})
defer ffclient.Close()

This example will load a file from an HTTP endpoint and will refresh the flags every 3 seconds (if you omit the PollInterval, the default value is 60 seconds).

Now you can evaluate your flags anywhere in your code.

user := ffuser.NewUser("user-unique-key")
hasFlag, _ := ffclient.BoolVariation("test-flag", user, false)
if hasFlag {
    // flag "test-flag" is true for the user
} else {
    // flag "test-flag" is false for the user
}

You can find more example programs in the examples/ directory.

Configuration

The configuration is set with ffclient.Config{} and you can give it to ffclient.Init() the initialization function.

Example:

ffclient.Init(ffclient.Config{ 
    PollInterval:   3,
    Logger:         log.New(file, "/tmp/log", 0),
    Context:        context.Background(),
    Retriever:      &ffclient.FileRetriever{Path: "testdata/test.yaml"},
    Webhooks:       []ffclient.WebhookConfig{
        {
            PayloadURL: " https://example.com/hook",
            Secret:     "Secret",
            Meta: map[string]string{
                "app.name": "my app",
            },
        },
    },
})
Descriptions
PollInterval Number of seconds to wait before refreshing the flags.
The default value is 60 seconds.
Logger Logger used to log what go-feature-flag is doing.
If no logger is provided the module will not log anything.
Context The context used by the retriever.
The default value is context.Background().
Retriever The configuration retriever you want to use to get your flag file (see Where do I store my flags file for the configuration details).
Webhooks List of webhooks to call when your flag file has changed (see webhook section for more details).

Where do I store my flags file

go-feature-flags support different ways of retrieving the flag file.
We can have only one source for the file, if you set multiple sources in your configuration, only one will be take in consideration.

From GitHub (click to see details)
err := ffclient.Init(ffclient.Config{
    PollInterval: 3,
    Retriever: &ffclient.GithubRetriever{
        RepositorySlug: "thomaspoignant/go-feature-flag",
        Branch: "main",
        FilePath: "testdata/test.yaml",
        GithubToken: "XXXX",
        Timeout: 2 * time.Second,
    },
})
defer ffclient.Close()

To configure the access to your GitHub file:

  • RepositorySlug: your GitHub slug org/repo-name. MANDATORY
  • FilePath: the path of your file. MANDATORY
  • Branch: the branch where your file is (default is main).
  • GithubToken: Github token is used to access a private repository, you need the repo permission (how to create a GitHub token).
  • Timeout: Timeout for the HTTP call (default is 10 seconds).

⚠️ GitHub has rate limits, so be sure to not reach them when setting your PollInterval.

From an HTTP endpoint (click to see details)
err := ffclient.Init(ffclient.Config{
    PollInterval: 3,
    Retriever: &ffclient.HTTPRetriever{
        URL:    "http://example.com/test.yaml",
        Timeout: 2 * time.Second,
    },
})
defer ffclient.Close()

To configure your HTTP endpoint:

  • URL: location of your file. MANDATORY
  • Method: the HTTP method you want to use (default is GET).
  • Body: If you need a body to get the flags.
  • Header: Header you should pass while calling the endpoint (useful for authorization).
  • Timeout: Timeout for the HTTP call (default is 10 seconds).
From a S3 Bucket (click to see details)
err := ffclient.Init(ffclient.Config{
    PollInterval: 3,
    Retriever: &ffclient.S3Retriever{
        Bucket: "tpoi-test",
        Item:   "test.yaml",
        AwsConfig: aws.Config{
            Region: aws.String("eu-west-1"),
        },
    },
})
defer ffclient.Close()

To configure your S3 file location:

  • Bucket: The name of your bucket. MANDATORY
  • Item: The location of your file in the bucket. MANDATORY
  • AwsConfig: An instance of aws.Config that configure your access to AWS (see this documentation for more info). MANDATORY
From a file (click to see details)
err := ffclient.Init(ffclient.Config{
    PollInterval: 3,
    Retriever: &ffclient.FileRetriever{
        Path: "file-example.yaml",
    },
})
defer ffclient.Close()

To configure your File retriever:

  • Path: location of your file. MANDATORY

I will not recommend using a file to store your flags except if it is in a shared folder for all your services.

Flags file format

go-feature-flag is to avoid to have to host a backend to manage your feature flags and to keep them centralized by using a file a source.
Your file should be a YAML file with a list of flags (see example).

A flag configuration looks like:

test-flag:
  percentage: 100
  rule: key eq "random-key"
  true: true
  false: false
  default: false
  disable: false
test-flag mandatory Name of the flag. It should be unique.
percentage optional Percentage of the users affect by the flag.
Default value is 0
rule optional This is the query use to select on which user the flag should apply.
Rule format is describe in the rule format section.
If no rule set, the flag apply to all users (percentage still apply).
true mandatory The value return by the flag if apply to the user (rule is evaluated to true) and user is in the active percentage.
false mandatory The value return by the flag if apply to the user (rule is evaluated to true) and user is not in the active percentage.
default mandatory The value return by the flag if not apply to the user (rule is evaluated to false).
disable optional True if the flag is disabled.

Rule format

The rule format is based on the nikunjy/rules library.

All the operations can be written capitalized or lowercase (ex: eq or EQ can be used).
Logical Operations supported are AND OR.

Compare Expression and their definitions (a|b means you can use either one of the two a or b):

eq|==: equals to 
ne|!=: not equals to
lt|<: less than 
gt|>: greater than
le|<=: less than equal to
ge|>=: greater than equal to 
co: contains 
sw: starts with 
ew: ends with
in: in a list
pr: present
not: not of a logical expression

Examples

  • Select a specific user: key eq "[email protected]"
  • Select all identified users: anonymous ne true
  • Select a user with a custom property: userId eq "12345"

Users

Feature flag targeting and rollouts are all determined by the user you pass to your Variation calls.
The SDK defines a User struct and a UserBuilder to make this easy.

Here's an example:

// User with only a key
user1 := ffuser.NewUser("user1-key")

// User with a key plus other attributes
user2 = ffuser.NewUserBuilder("user2-key").
 AddCustom("firstname", "John").
 AddCustom("lastname", "Doe").
 AddCustom("email", "[email protected]").
 Build()

The most common attribute is the user's key. In this case we've used the strings "user1-key" and "user2-key".
The user key is the only mandatory user attribute. The key should also uniquely identify each user. You can use a primary key, an e-mail address, or a hash, as long as the same user always has the same key. We recommend using a hash if possible.

Custom attributes are one of the most powerful features. They let you have rules on these attributes and target users according to any data that you want.

Variation

The Variation methods determine whether a flag is enabled or not for a specific user. There is a Variation method for each type: BoolVariation, IntVariation, Float64Variation, StringVariation, JSONArrayVariation and JSONVariation.

result, _ := ffclient.BoolVariation("your.feature.key", user, false)

// result is now true or false depending on the setting of this boolean feature flag

Variation methods take the feature flag key, a User, and a default value.

The default value is return when an error is encountered (ffclient not initialized, variation with wrong type, flag does not exist ...).
In the example, if the flag your.feature.key does not exists, result will be false.
Not that you will always have a usable value in the result.

Webhook

If you want to be informed when a flag has changed outside of your app, you can configure a webhook.

ffclient.Config{ 
    // ...
    Webhooks: []ffclient.WebhookConfig{
        {
            PayloadURL: " https://example.com/hook",
            Secret:     "Secret",
            Meta: map[string]string{
                "app.name": "my app",
            },
        },
    },
}
PayloadURL mandatory The complete URL of your API (we will send a POST request to this URL, see format)
Secret optional A secret key you can share with your webhook. We will use this key to sign the request (see signature section for more details).
Meta optional A list of key value that will be add in your request, this is super usefull if you to add information on the current running instance of your app.
By default the hostname is always added in the meta informations.

Format

If you have configured a webhook, a POST request will be sent to the PayloadURL with a body in this format:

{
    "meta": {
        "hostname": "server01",
        // ...
    },
    "flags": {
        "deleted": {}, // map of your deleted flags
        "added": {}, // map of your added flags
        "updated": {
            "flag-name": { // an object that contains old and new value
                "old_value": {},
                "new_value": {}
            }
        }
    }
}
Example
{
  "meta":{
      "hostname": "server01"
  },
  "flags":{
      "deleted": {
          "test-flag": {
              "rule": "key eq \"random-key\"",
              "percentage": 100,
              "true": true,
              "false": false,
              "default": false
          }
      },
      "added": {
          "test-flag3": {
              "percentage": 5,
              "true": "test",
              "false": "false",
              "default": "default"
          }
      },
      "updated": {
          "test-flag2": {
              "old_value": {
                  "rule": "key eq \"not-a-key\"",
                  "percentage": 100,
                  "true": true,
                  "false": false,
                  "default": false
              },
              "new_value": {
                  "disable": true,
                  "rule": "key eq \"not-a-key\"",
                  "percentage": 100,
                  "true": true,
                  "false": false,
                  "default": false
              }
          }
      }
  }
}

Signature

This header X-Hub-Signature-256 is sent if the webhook is configured with a secret. This is the HMAC hex digest of the request body, and is generated using the SHA-256 hash function and the secret as the HMAC key.

⚠️ The recommendation is to always use the Secret and on your API/webook always verify the signature key to be sure that you don't have a man in the middle attack.


Multiple flag configurations

go-feature-flag comes ready to use out of the box by calling the Init function and after that it will be available everywhere. Since most applications will want to use a single central flag configuration, the go-feature-flag package provides this. It is similar to a singleton.

In all of the examples above, they demonstrate using go-feature-flag in its singleton style approach.

Working with multiple go-feature-flag

You can also create many different go-feature-flag client for use in your application.
Each will have its own unique set of configurations and flags. Each can read from a different config file and from different places.
All of the functions that go-feature-flag package supports are mirrored as methods on a goFeatureFlag.

Example:

x, err := ffclient.New(Config{ Retriever: &ffclient.HTTPRetriever{{URL: "http://example.com/test.yaml",}})
defer x.Close()

y, err := ffclient.New(Config{ Retriever: &ffclient.HTTPRetriever{{URL: "http://example.com/test2.yaml",}})
defer y.Close()

user := ffuser.NewUser("user-key")
x.BoolVariation("test-flag", user, false)
y.BoolVariation("test-flag", user, false)

// ...

When working with multiple go-feature-flag, it is up to the user to keep track of the different go-feature-flag instances.

How can I contribute?

This project is open for contribution, see the contributor's guide for some helpful tips.

Owner
Thomas Poignant
Techlead and cloud architect, I like to build great apps and deploy them on the cloud. AWS Solution Architect Certified.
Thomas Poignant
Comments
  • (change) Move retrievers into sub-pacakges (or external libs?)

    (change) Move retrievers into sub-pacakges (or external libs?)

    Motivation

    The go-feature-flag library provides a nice and hopefully growing list of retrievers. Unfortunately all retrievers are made available in the top-level package, which means that all projects that do depend on go-feature-flag automatically pull in and compile all those dependencies, no matter what. With the recent addition of the kubernetes client the compile, lint times, and binary file sizes have increased quite significantly. In my case each each have doubled the least... and my local pre-commit hook running golangci-lint even went up to 200s.

    Requirements

    Users of go-feature-flag should be allowed to pull in only the dependencies they actually need. This can be achieved by moving the retrievers into their own packages like go-feature-flag/retrievers/... for example, or moving them into separate Repositories (which might be annoying maintenance wise...).

  • Add new GetFlagsFromCache public method

    Add new GetFlagsFromCache public method

    This allows retrieving flag cache metadata like version, rule etc so the application can use it for visibility purposes. i.e: you want to know what version of a specific flag your ffclient is currently using

    resolves #251

  • Kubernetes configmaps

    Kubernetes configmaps

    Description

    This PR adds initial support for JSON and YAML encoded flag data in a Kubernetes ConfigMap.

    Changes include

    • [ ] Bugfix (non-breaking change that solves an issue)
    • [X] New feature (non-breaking change that adds functionality)
    • [ ] Breaking changes (change that is not backward-compatible and/or changes current functionality)

    Closes issue(s)

    Resolve #213

    Checklist

    • [x] I have tested this code
    • [X] I have added unit test to cover this code
    • [X] I have updated the documentation (README.md and /docs)
    • [X] I have followed the contributing guide
  • Bump cloud.google.com/go/storage from 1.24.0 to 1.25.0

    Bump cloud.google.com/go/storage from 1.24.0 to 1.25.0

    Bumps cloud.google.com/go/storage from 1.24.0 to 1.25.0.

    Release notes

    Sourced from cloud.google.com/go/storage's releases.

    storage: v1.25.0

    1.25.0 (2022-08-11)

    Features

    • storage/internal: Add routing annotations (8a8ba85)
    • storage: refactor to use transport-agnostic interface (#6465) (d03c3e1)
    Commits
    • d21fc8e chore: release spanner 1.25.0 (#4666)
    • 7a56af0 feat(spanner/spansql): add support for STARTS_WITH function (#4670)
    • 4f04795 test(spanner): fix the json integration test (#4668)
    • b434d9d chore: release pubsub 1.16.0 (#4672)
    • 0440336 feat(pubsub): add topic message retention duration (#4520)
    • 2973995 chore(all): auto-regenerate gapics (#4657)
    • ade8ab1 feat(spanner): add support for JSON data type (#4104)
    • bc966a3 chore(storage): fix gRPC reader size/remain logic (#4662)
    • a2118f0 fix(spanner/spannertest): Fix the "LIKE" clause handling for prefix and suffi...
    • cde8697 fix(spanner): invalid numeric should throw an error (#3926)
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
  • Make `getFlagFromCache` method public

    Make `getFlagFromCache` method public

    Motivation

    I'm running go-feature-flags in my API and in my health endpoint I'd like to return all the flags that I have configured and the current version in cache. I see that the getFlagFromCache method could give me all the information that I need but it's currently private. Is it ok if we made it public? Happy to send a PR to address that.

  • added Retriever for Google Storage #166

    added Retriever for Google Storage #166

    Description

    GC Storage support was added according to #166. Can be tested by adding a flag file to google storage bucket and running the http example with a ffclient.GCPRetriever.

    Changes include

    • [ ] Bugfix (non-breaking change that solves an issue)
    • [x] New feature (non-breaking change that adds functionality)
    • [ ] Breaking changes (change that is not backward-compatible and/or changes current functionality)

    Closes issue(s)

    Resolve #166

    Checklist

    • [x] I have tested this code
    • [x] I have added unit test to cover this code
    • [x] I have updated the documentation (README.md and /docs)
    • [x] I have followed the contributing guide
  • Add environment parameter in config

    Add environment parameter in config

    Description

    Checking the current environment / flagging by environment is a common use cases for projects I'm involved in, so this adds environment awareness to feature flags. You can set environment as a field in the Config passed to Init, then check them in rule (e.g. rule: env == "dev")

    I realize I need to address tests/docs, but wanted to get feedback on the approach first to see if it was acceptable.

    Changes include

    • [ ] Bugfix (non-breaking change that solves an issue)
    • [x] New feature (non-breaking change that adds functionality)
    • [ ] Breaking changes (change that is not backward-compatible and/or changes current functionality)

    Closes issue(s)

    Resolve #175

    Checklist

    • [x] I have tested this code
    • [x] I have added unit test to cover this code
    • [x] I have updated the documentation (README.md and /docs)
    • [x] I have followed the contributing guide
  • (change) Make Notifier interface publicly implementable

    (change) Make Notifier interface publicly implementable

    Motivation

    Make the Notifier interface publicly implementable.

    Hi, thanks for making this library! I would like to output feature flag changes to our internal Grafana via the Annotations API.

    The current Webhook notifier doesn't satisfy our need, as we would like to format the text for the annotation based on the diff. We could do this via an intermediate web server that translates the Webhook notifier payload for Grafana, but it would be nice to do it without the intermediate server.

    Requirements

    Ideally, go-feature-flag should allow the notifier interface to be implemented publically and support custom notifiers passed in completely via the Config. Currently is not possible because the GetNotifier interface returns the internal Notifier interface. Also, the Notifier interface accepts an internal model.DiffCache struct.

    Would it be possible to make these part of the public API? I think it may be just a matter of taking it out of the internal package and into a public notifier package?

    I'm more than willing to put a PR in, if you are okay with making it public. Thanks!

  • (feature) add kubernetes config retriever

    (feature) add kubernetes config retriever

    Requirements

    Would you be interested in contributions to fetch configs from a kubernetes config map? I'd like to give it a try if that's something that you're willing to add here.

  • Bump k8s.io/api from 0.25.3 to 0.25.4

    Bump k8s.io/api from 0.25.3 to 0.25.4

    Bumps k8s.io/api from 0.25.3 to 0.25.4.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
  • (change) Export kubernetes interface in kubernetes configmap retriever

    (change) Export kubernetes interface in kubernetes configmap retriever

    Motivation

    Currently the kubernetes configmap retriever only support to pass through rest.Config to it and resolve a clientset during retrieve, restConfig in kubernetes is generally hard to debug, and when something went wrong(nil pointer panic etc), seldom could we extract valuable information from it, while in current retriever example, rest.Config is the only exposed field and we need initialize kubernetes clientset during retrieve.

    Requirements

    update the kubernetesConfigRetriever from

    // KubernetesRetriever is a configuration struct for a Kubernetes retriever.
    type KubernetesRetriever struct {
    	Namespace     string
    	ConfigMapName string
    	Key           string
    	ClientConfig  restclient.Config
    	client        kubernetes.Interface
    }
    

    into

    // KubernetesRetriever is a configuration struct for a Kubernetes retriever.
    type KubernetesRetriever struct {
    	Namespace     string
    	ConfigMapName string
    	Key           string
    	ClientConfig  restclient.Config
    	Client        kubernetes.Interface
    }
    
  • Editor react

    Editor react

    Description

    Add the new editor directly in docusaurus. This is the MVP of the solution

    Changes include

    • [ ] Bugfix (non-breaking change that solves an issue)
    • [x] New feature (non-breaking change that adds functionality)
    • [ ] Breaking changes (change that is not backward-compatible and/or changes current functionality)

    Closes issue(s)

    #421

    Checklist

    • [x] I have tested this code
    • [ ] I have added unit test to cover this code
    • [ ] I have updated the documentation (README.md and /docs)
    • [x] I have followed the contributing guide
  • (change) Build editor into docusaurus

    (change) Build editor into docusaurus

    Motivation

    Today the flag editor is made for the v0.x.x with the version v1.x.x it is not working with the right format.

    Requirements

    We need the editor into docusaurus (in react) and compatible with the new format.

  • Upgrading github.com/nikunjy/rules

    Upgrading github.com/nikunjy/rules

    Description

    Upgrading github.com/nikunjy/rules

    Changes include

    • [ ] Bugfix (non-breaking change that solves an issue)
    • [ ] New feature (non-breaking change that adds functionality)
    • [ ] Breaking changes (change that is not backward-compatible and/or changes current functionality)

    Closes issue(s)

    https://github.com/thomaspoignant/go-feature-flag/issues/348

    Resolve #

    Checklist

    • [ ] I have tested this code
    • [ ] I have added unit test to cover this code
    • [ ] I have updated the documentation (README.md and /docs)
    • [ ] I have followed the contributing guide
  • V1.0.0

    V1.0.0

    Description

    This PR is a long-running pull request for version v1.0.0 of go-feature-flag.

    Changes include

    • [ ] Bugfix (non-breaking change that solves an issue)
    • [ ] New feature (non-breaking change that adds functionality)
    • [ ] Breaking changes (change that is not backward-compatible and/or changes current functionality)

    Closes issue(s)

    Resolve #

    Checklist

    • [ ] I have tested this code
    • [ ] I have added unit test to cover this code
    • [ ] I have updated the documentation (README.md and /docs)
    • [ ] I have followed the contributing guide
  • (feature) Adding simpler format

    (feature) Adding simpler format

    Requirements

    Following the idea of @urso on this discussion #229 it could be great to add a simpler format to have an easy way to configure some flags.

    The first proposal are:

    Always true

    dev-flag:
      value: true  # can be an integer as well
    

    A/B testing

    new-feature:
      a/b-test:   # boolean flag that returns true for 60% of our users
        percentage: 60
    

    These are examples, we may propose something different if needed.

Fishserver is designed to quickly add HTTP handlers to HTTP servers. It supports registration of various HTTP
Fishserver is designed to quickly add HTTP handlers to HTTP servers. It supports registration of various HTTP

Fishserver is designed to quickly add HTTP handlers to HTTP servers. It supports registration of various HTTP. Handler interface types such as Gin Engine, Go's built-in HTTP. HandlerFunc, or http.ServeMux. The HTTP server can be configured quickly with options and can be used for test cases.

Nov 1, 2021
a simple http server as replacement of python -m http.server

ser a simple http server as replacement of python -m http.server

Dec 5, 2022
Flagr is a feature flagging, A/B testing and dynamic configuration microservice
Flagr is a feature flagging, A/B testing and dynamic configuration microservice

Introduction Flagr is an open source Go service that delivers the right experience to the right entity and monitors the impact. It provides feature fl

Dec 25, 2022
OpenAPI specs for your Go server, generated at server runtime. No CLI, no code generation, and no HTTP

Overview "oas" is short for "OpenAPI Spec". Go package for generating OpenAPI docs at runtime. Non-features: No code generation. No CLI. No magic comm

Dec 3, 2021
A local server with real-time reload function designed for static website preview or development

中文 | English ?? 介绍 reserver 是一款为静态网站预览或开发设计的具有实时重新加载功能的本地服务器。 其主要运用场景为: 单页应用的预览(例如Vue编译之后的项目不可以直接通过file://协议进行访问) 具有ajax请求的页面(因浏览器安全限制,默认禁止file://协议进行

Aug 23, 2022
A simple http-web server logging incoming requests to stdout with simple http-interface.
A simple http-web server logging incoming requests to stdout with simple http-interface.

http-cli-echo-logger A simple http-web server logging incoming requests to stdout with simple http-interface. Run locally go run ./cmd/main.go Default

Jul 18, 2022
Web server for running Brainfuck on the backend

Brainfuck Web Server Web server for running Brainfuck on the backend Run go run . <brainfuck file> The server will start on port 8080 by default. You

Oct 25, 2021
Backend for Workery application server implemented in Golang

workery-server Backend for Workery application server implemented in Golang. This is a rewrite of the workery-django project. Development Goals: Rewri

Dec 14, 2022
Minimal HTTP File Server for pentesting written in Go
Minimal HTTP File Server for pentesting written in Go

Golang implementation of simple HTTP server with upload feature.

Aug 4, 2022
✨ A lightweight HTTP server based on GO, will try to detect your OS and architecture and return as SHELL script. ✨
✨ A lightweight HTTP server based on GO, will try to detect your OS and architecture and return as SHELL script. ✨

✨ A lightweight HTTP server based on GO, will try to detect your OS and architecture and return as SHELL script. ✨

Dec 14, 2022
CasaOS - A simple, easy-to-use, elegant open-source home server system.
CasaOS - A simple, easy-to-use, elegant open-source home server system.

CasaOS - A simple, easy-to-use, elegant open-source home server system. CasaOS is an open-source home server system based on the Docker ecosystem and

Jan 8, 2023
:tophat: Small self-contained pure-Go web server with Lua, Markdown, HTTP/2, QUIC, Redis and PostgreSQL support
:tophat: Small self-contained pure-Go web server with Lua, Markdown, HTTP/2, QUIC, Redis and PostgreSQL support

Web server with built-in support for QUIC, HTTP/2, Lua, Markdown, Pongo2, HyperApp, Amber, Sass(SCSS), GCSS, JSX, BoltDB (built-in, stores the databas

Jan 1, 2023
Opinionated boilerplate Golang HTTP server with CORS, OPA, Prometheus, rate-limiter for API and static website.
Opinionated boilerplate Golang HTTP server with CORS, OPA, Prometheus, rate-limiter for API and static website.

Teal.Finance/Server Opinionated boilerplate HTTP server with CORS, OPA, Prometheus, rate-limiter… for API and static website. Origin This library was

Nov 3, 2022
HTTP server receives events and publishes them to STAN
HTTP server receives events and publishes them to STAN

Publishes events to Nats Streaming(STAN) synchornously and asynchronously. Cache events's publish-state using Redis and Store events using MongoDB.

Dec 30, 2022
Formrecevr is a simple and lightweight from receiver backend primarily designed for (but not limited to) static websites.

Formrecevr Formrecevr (pronunced "Form receiver") is a simple and lightweight from receiver backend primarily designed for (but not limited to) static

Apr 17, 2022
The Zuri Core is an open-source API that serves as the backend and backbone of Zuri Chat
The Zuri Core is an open-source API that serves as the backend and backbone of Zuri Chat

The Zuri Core is an open-source API that serves as the backend and backbone of Zuri Chat

Dec 26, 2022
A local webserver for developers
 A local webserver for developers

devd: a local webserver for developers Install Go to the releases page, download the package for your OS, and copy the binary to somewhere on your PAT

Dec 27, 2022
Go web server - A web server that can accept a GET request and serve a response.

go_web_server A web server that can accept a GET request and serve a response. Go is a great language for creating simple yet efficient web servers an

Jan 3, 2022