1
0
Fork 0
mirror of https://github.com/Luzifer/go-holidays.git synced 2024-12-26 05:41:18 +00:00

Add README page for / path

This commit is contained in:
Knut Ahlers 2017-02-02 03:37:43 +01:00
parent 3c8fe7ceda
commit 9fe048b5d0
Signed by: luzifer
GPG key ID: DC2729FDD34BE99E
4 changed files with 300 additions and 0 deletions

View file

@ -7,6 +7,8 @@ WORKDIR /go/src/github.com/Luzifer/go-holidays/cmd/holiday-api
RUN set -ex \ RUN set -ex \
&& apk add --update git ca-certificates \ && apk add --update git ca-certificates \
&& go get -u github.com/jteeuwen/go-bindata/... \
&& go generate \
&& go install -ldflags "-X main.version=$(git describe --tags || git rev-parse --short HEAD || echo dev)" \ && go install -ldflags "-X main.version=$(git describe --tags || git rev-parse --short HEAD || echo dev)" \
&& apk del --purge git && apk del --purge git

192
cmd/holiday-api/assets.go Normal file
View file

@ -0,0 +1,192 @@
// Code generated by go-bindata.
// sources:
// index.html
// DO NOT EDIT!
package main
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
)
// bindataRead reads the given file from disk. It returns an error on failure.
func bindataRead(path, name string) ([]byte, error) {
buf, err := ioutil.ReadFile(path)
if err != nil {
err = fmt.Errorf("Error reading asset %s at %s: %v", name, path, err)
}
return buf, err
}
type asset struct {
bytes []byte
info os.FileInfo
}
// indexHtml reads file data from disk. It returns an error on failure.
func indexHtml() (*asset, error) {
path := filepath.Join(rootDir, "index.html")
name := "index.html"
bytes, err := bindataRead(path, name)
if err != nil {
return nil, err
}
fi, err := os.Stat(path)
if err != nil {
err = fmt.Errorf("Error reading asset info %s at %s: %v", name, path, err)
}
a := &asset{bytes: bytes, info: fi}
return a, err
}
// Asset loads and returns the asset for the given name.
// It returns an error if the asset could not be found or
// could not be loaded.
func Asset(name string) ([]byte, error) {
cannonicalName := strings.Replace(name, "\\", "/", -1)
if f, ok := _bindata[cannonicalName]; ok {
a, err := f()
if err != nil {
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
}
return a.bytes, nil
}
return nil, fmt.Errorf("Asset %s not found", name)
}
// MustAsset is like Asset but panics when Asset would return an error.
// It simplifies safe initialization of global variables.
func MustAsset(name string) []byte {
a, err := Asset(name)
if err != nil {
panic("asset: Asset(" + name + "): " + err.Error())
}
return a
}
// AssetInfo loads and returns the asset info for the given name.
// It returns an error if the asset could not be found or
// could not be loaded.
func AssetInfo(name string) (os.FileInfo, error) {
cannonicalName := strings.Replace(name, "\\", "/", -1)
if f, ok := _bindata[cannonicalName]; ok {
a, err := f()
if err != nil {
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
}
return a.info, nil
}
return nil, fmt.Errorf("AssetInfo %s not found", name)
}
// AssetNames returns the names of the assets.
func AssetNames() []string {
names := make([]string, 0, len(_bindata))
for name := range _bindata {
names = append(names, name)
}
return names
}
// _bindata is a table, holding each asset generator, mapped to its name.
var _bindata = map[string]func() (*asset, error){
"index.html": indexHtml,
}
// AssetDir returns the file names below a certain
// directory embedded in the file by go-bindata.
// For example if you run go-bindata on data/... and data contains the
// following hierarchy:
// data/
// foo.txt
// img/
// a.png
// b.png
// then AssetDir("data") would return []string{"foo.txt", "img"}
// AssetDir("data/img") would return []string{"a.png", "b.png"}
// AssetDir("foo.txt") and AssetDir("notexist") would return an error
// AssetDir("") will return []string{"data"}.
func AssetDir(name string) ([]string, error) {
node := _bintree
if len(name) != 0 {
cannonicalName := strings.Replace(name, "\\", "/", -1)
pathList := strings.Split(cannonicalName, "/")
for _, p := range pathList {
node = node.Children[p]
if node == nil {
return nil, fmt.Errorf("Asset %s not found", name)
}
}
}
if node.Func != nil {
return nil, fmt.Errorf("Asset %s not found", name)
}
rv := make([]string, 0, len(node.Children))
for childName := range node.Children {
rv = append(rv, childName)
}
return rv, nil
}
type bintree struct {
Func func() (*asset, error)
Children map[string]*bintree
}
var _bintree = &bintree{nil, map[string]*bintree{
"index.html": &bintree{indexHtml, map[string]*bintree{}},
}}
// RestoreAsset restores an asset under the given directory
func RestoreAsset(dir, name string) error {
data, err := Asset(name)
if err != nil {
return err
}
info, err := AssetInfo(name)
if err != nil {
return err
}
err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755))
if err != nil {
return err
}
err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
if err != nil {
return err
}
err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
if err != nil {
return err
}
return nil
}
// RestoreAssets restores an asset under the given directory recursively
func RestoreAssets(dir, name string) error {
children, err := AssetDir(name)
// File
if err != nil {
return RestoreAsset(dir, name)
}
// Dir
for _, child := range children {
err = RestoreAssets(dir, filepath.Join(name, child))
if err != nil {
return err
}
}
return nil
}
func _filePath(dir, name string) string {
cannonicalName := strings.Replace(name, "\\", "/", -1)
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
}

View file

@ -0,0 +1,98 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<title>holiday-api Documentation</title>
<!-- Bootstrap -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap-theme.min.css"
integrity="sha256-ZT4HPpdCOt2lvDkXokHuhJfdOKSPFLzeAJik5U/Q+l4=" crossorigin="anonymous" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootswatch/3.3.7/superhero/bootstrap.min.css"
integrity="sha256-LEplvgQTKatd65f2Z/JThrYx/sdoKygi0dsC1h5sInE=" crossorigin="anonymous" />
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"
integrity="sha256-3Jy/GbSLrg0o9y5Z5n1uw0qxZECH7C6OQpVBgNFYa0g=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js"
integrity="sha256-g6iAfvZp+nDQ2TdTR/VVKJf3bGro4ub5fvWSWVRi2NE=" crossorigin="anonymous"></script>
<![endif]-->
</head>
<body>
<div class="container">
<div class="col-md-12" id="display">
# holiday-api Documentation
This instance of `holiday-api` is a convenient wrapper around my [go-holiday library](https://github.com/Luzifer/go-holidays) which contains holidays for different countries. With this wrapper you can request a JSON output for a specific country or state within a country using [ISO 3166-1 alpha-2 country codes](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). For some countries (for example Germany) the corresponding state code extension is supported.
## Usage
The supported URL scheme is `/{country-code}/{year}` while `{year}` is optional and if not set the current year is used.
Examples:
- [`/us`](/us) - Federal holidays for the United States for the current year
- [`/de/2017`](/de/2017) - National holidays in Germany for 2017
- [`/de-by/2017`](/de-by/2017) - Holidays for Bavaria for 2017 (Uses [ISO 3166-2:DE](https://en.wikipedia.org/wiki/ISO_3166-2:DE) codes)
No request limits are enforced so please play nice with the API.
## Response
The API will respond with
- `HTTP 200` and a JSON array if the query was successful
- `HTTP 404` if your URL is nvalid.
- `HTTP 500` if the requested country-code is not included / supported
### JSON format
Each entry consists of four keys:
- `name`: Name of the holiday in English language
- `localized_name`: A mapping of different localizations (key is an ISO 3166-1 alpha-2 country code)
- `date`: A string representation of the date in `YYYY-MM-DD` notation
- `parsed_date`: The date as a DateTime string with timezone of the server running the API
```json
[
{
name: "New Year's Day",
localized_name: {
de: "Neujahrstag"
},
date: "2017-01-01",
parsed_date: "2017-01-01T00:00:00Z"
},
{
name: "Good Friday",
localized_name: {
de: "Karfreitag"
},
date: "2017-04-14",
parsed_date: "2017-04-14T00:00:00Z"
}
]
```
## Contributions
If you are fluent in writing Go and know about holidays of a country not yet available inside the library please get in touch with me. Either using an issue or a pull-request in the [repository](https://github.com/Luzifer/go-holidays) or using any method on my website: [ahlers.me](https://ahlers.me/)
</div>
</div>
<a href="https://github.com/Luzifer/go-holidays" class="github-corner" aria-label="View source on Github"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#70B7FD; color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"
integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"
integrity="sha256-U5ZEeKfGNOja007MMD3YBI0A3OSZOQbeG6z2f2Y0hu8=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.6/marked.min.js"
integrity="sha256-mJAzKDq6kSoKqZKnA6UNLtPaIj8zT2mFnWu/GSouhgQ=" crossorigin="anonymous"></script>
<script>
$(function(){ $('#display').html(marked($('#display').html())); });
</script>
</body>
</html>

View file

@ -1,5 +1,7 @@
package main package main
//go:generate go-bindata -pkg $GOPACKAGE -o assets.go index.html
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -38,6 +40,7 @@ func main() {
r := mux.NewRouter() r := mux.NewRouter()
r.HandleFunc("/{country-code:[a-z-]+}/{year:[0-9]{4}}", handleHolidays) r.HandleFunc("/{country-code:[a-z-]+}/{year:[0-9]{4}}", handleHolidays)
r.HandleFunc("/{country-code:[a-z-]+}", handleHolidays) r.HandleFunc("/{country-code:[a-z-]+}", handleHolidays)
r.HandleFunc("/", handleReadme)
http.ListenAndServe(cfg.Listen, r) http.ListenAndServe(cfg.Listen, r)
} }
@ -66,3 +69,8 @@ func handleHolidays(res http.ResponseWriter, r *http.Request) {
res.Header().Set("Content-Type", "application/json") res.Header().Set("Content-Type", "application/json")
json.NewEncoder(res).Encode(holidays) json.NewEncoder(res).Encode(holidays)
} }
func handleReadme(res http.ResponseWriter, r *http.Request) {
readme, _ := Asset("index.html")
res.Write(readme)
}