mirror of https://github.com/fatedier/frp
fatedier
9 years ago
35 changed files with 3064 additions and 49 deletions
@ -0,0 +1,14 @@
|
||||
FROM golang:1.5 |
||||
|
||||
MAINTAINER fatedier |
||||
|
||||
RUN echo "[common]\nbind_addr = 0.0.0.0\nbind_port = 7000\n[wiki]\npasswd = 123\nbind_addr = 0.0.0.0\nlisten_port = 80" > /usr/share/frps.ini |
||||
|
||||
ADD ./ /usr/share/frp/ |
||||
|
||||
RUN cd /usr/share/frp && make |
||||
|
||||
EXPOSE 80 |
||||
EXPOSE 7000 |
||||
|
||||
CMD ["/usr/share/frp/bin/frps -c /usr/share/frps.ini"] |
@ -0,0 +1,25 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects) |
||||
*.o |
||||
*.a |
||||
*.so |
||||
|
||||
# Folders |
||||
_obj |
||||
_test |
||||
|
||||
# Architecture specific extensions/prefixes |
||||
*.[568vq] |
||||
[568vq].out |
||||
|
||||
*.cgo1.go |
||||
*.cgo2.c |
||||
_cgo_defun.c |
||||
_cgo_gotypes.go |
||||
_cgo_export.* |
||||
|
||||
_testmain.go |
||||
|
||||
*.exe |
||||
|
||||
# coverage droppings |
||||
profile.cov |
@ -0,0 +1,31 @@
|
||||
# Travis CI (http://travis-ci.org/) is a continuous integration |
||||
# service for open source projects. This file configures it |
||||
# to run unit tests for docopt-go. |
||||
|
||||
language: go |
||||
|
||||
go: |
||||
- 1.4 |
||||
- 1.5 |
||||
- tip |
||||
|
||||
matrix: |
||||
fast_finish: true |
||||
|
||||
before_install: |
||||
- go get golang.org/x/tools/cmd/vet |
||||
- go get golang.org/x/tools/cmd/cover |
||||
- go get github.com/golang/lint/golint |
||||
- go get github.com/mattn/goveralls |
||||
|
||||
install: |
||||
- go get -d -v ./... && go build -v ./... |
||||
|
||||
script: |
||||
- go vet -x ./... |
||||
- $HOME/gopath/bin/golint ./... |
||||
- go test -v ./... |
||||
- go test -covermode=count -coverprofile=profile.cov . |
||||
|
||||
after_script: |
||||
- $HOME/gopath/bin/goveralls -coverprofile=profile.cov -service=travis-ci |
@ -0,0 +1,20 @@
|
||||
The MIT License (MIT) |
||||
|
||||
Copyright (c) 2013 Keith Batten |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of |
||||
this software and associated documentation files (the "Software"), to deal in |
||||
the Software without restriction, including without limitation the rights to |
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of |
||||
the Software, and to permit persons to whom the Software is furnished to do so, |
||||
subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
@ -0,0 +1,88 @@
|
||||
docopt-go |
||||
========= |
||||
|
||||
[![Build Status](https://travis-ci.org/docopt/docopt.go.svg?branch=master)](https://travis-ci.org/docopt/docopt.go) |
||||
[![Coverage Status](https://coveralls.io/repos/docopt/docopt.go/badge.png)](https://coveralls.io/r/docopt/docopt.go) |
||||
[![GoDoc](https://godoc.org/github.com/docopt/docopt.go?status.png)](https://godoc.org/github.com/docopt/docopt.go) |
||||
|
||||
An implementation of [docopt](http://docopt.org/) in the |
||||
[Go](http://golang.org/) programming language. |
||||
|
||||
**docopt** helps you create *beautiful* command-line interfaces easily: |
||||
|
||||
```go |
||||
package main |
||||
|
||||
import ( |
||||
"fmt" |
||||
"github.com/docopt/docopt-go" |
||||
) |
||||
|
||||
func main() { |
||||
usage := `Naval Fate. |
||||
|
||||
Usage: |
||||
naval_fate ship new <name>... |
||||
naval_fate ship <name> move <x> <y> [--speed=<kn>] |
||||
naval_fate ship shoot <x> <y> |
||||
naval_fate mine (set|remove) <x> <y> [--moored|--drifting] |
||||
naval_fate -h | --help |
||||
naval_fate --version |
||||
|
||||
Options: |
||||
-h --help Show this screen. |
||||
--version Show version. |
||||
--speed=<kn> Speed in knots [default: 10]. |
||||
--moored Moored (anchored) mine. |
||||
--drifting Drifting mine.` |
||||
|
||||
arguments, _ := docopt.Parse(usage, nil, true, "Naval Fate 2.0", false) |
||||
fmt.Println(arguments) |
||||
} |
||||
``` |
||||
|
||||
**docopt** parses command-line arguments based on a help message. Don't |
||||
write parser code: a good help message already has all the necessary |
||||
information in it. |
||||
|
||||
## Installation |
||||
|
||||
⚠ Use the alias “docopt-go”. To use docopt in your Go code: |
||||
|
||||
```go |
||||
import "github.com/docopt/docopt-go" |
||||
``` |
||||
|
||||
To install docopt according to your `$GOPATH`: |
||||
|
||||
```console |
||||
$ go get github.com/docopt/docopt-go |
||||
``` |
||||
|
||||
## API |
||||
|
||||
```go |
||||
func Parse(doc string, argv []string, help bool, version string, |
||||
optionsFirst bool, exit ...bool) (map[string]interface{}, error) |
||||
``` |
||||
Parse `argv` based on the command-line interface described in `doc`. |
||||
|
||||
Given a conventional command-line help message, docopt creates a parser and |
||||
processes the arguments. See |
||||
https://github.com/docopt/docopt#help-message-format for a description of the |
||||
help message format. If `argv` is `nil`, `os.Args[1:]` is used. |
||||
|
||||
docopt returns a map of option names to the values parsed from `argv`, and an |
||||
error or `nil`. |
||||
|
||||
More documentation for docopt is available at |
||||
[GoDoc.org](https://godoc.org/github.com/docopt/docopt.go). |
||||
|
||||
## Testing |
||||
|
||||
All tests from the Python version are implemented and passing |
||||
at [Travis CI](https://travis-ci.org/docopt/docopt.go). New |
||||
language-agnostic tests have been added |
||||
to [test_golang.docopt](test_golang.docopt). |
||||
|
||||
To run tests for docopt-go, use `go test`. |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,9 @@
|
||||
r"""usage: prog [NAME_-2]...""" |
||||
$ prog 10 20 |
||||
{"NAME_-2": ["10", "20"]} |
||||
|
||||
$ prog 10 |
||||
{"NAME_-2": ["10"]} |
||||
|
||||
$ prog |
||||
{"NAME_-2": []} |
@ -0,0 +1,957 @@
|
||||
r"""Usage: prog |
||||
|
||||
""" |
||||
$ prog |
||||
{} |
||||
|
||||
$ prog --xxx |
||||
"user-error" |
||||
|
||||
|
||||
r"""Usage: prog [options] |
||||
|
||||
Options: -a All. |
||||
|
||||
""" |
||||
$ prog |
||||
{"-a": false} |
||||
|
||||
$ prog -a |
||||
{"-a": true} |
||||
|
||||
$ prog -x |
||||
"user-error" |
||||
|
||||
|
||||
r"""Usage: prog [options] |
||||
|
||||
Options: --all All. |
||||
|
||||
""" |
||||
$ prog |
||||
{"--all": false} |
||||
|
||||
$ prog --all |
||||
{"--all": true} |
||||
|
||||
$ prog --xxx |
||||
"user-error" |
||||
|
||||
|
||||
r"""Usage: prog [options] |
||||
|
||||
Options: -v, --verbose Verbose. |
||||
|
||||
""" |
||||
$ prog --verbose |
||||
{"--verbose": true} |
||||
|
||||
$ prog --ver |
||||
{"--verbose": true} |
||||
|
||||
$ prog -v |
||||
{"--verbose": true} |
||||
|
||||
|
||||
r"""Usage: prog [options] |
||||
|
||||
Options: -p PATH |
||||
|
||||
""" |
||||
$ prog -p home/ |
||||
{"-p": "home/"} |
||||
|
||||
$ prog -phome/ |
||||
{"-p": "home/"} |
||||
|
||||
$ prog -p |
||||
"user-error" |
||||
|
||||
|
||||
r"""Usage: prog [options] |
||||
|
||||
Options: --path <path> |
||||
|
||||
""" |
||||
$ prog --path home/ |
||||
{"--path": "home/"} |
||||
|
||||
$ prog --path=home/ |
||||
{"--path": "home/"} |
||||
|
||||
$ prog --pa home/ |
||||
{"--path": "home/"} |
||||
|
||||
$ prog --pa=home/ |
||||
{"--path": "home/"} |
||||
|
||||
$ prog --path |
||||
"user-error" |
||||
|
||||
|
||||
r"""Usage: prog [options] |
||||
|
||||
Options: -p PATH, --path=<path> Path to files. |
||||
|
||||
""" |
||||
$ prog -proot |
||||
{"--path": "root"} |
||||
|
||||
|
||||
r"""Usage: prog [options] |
||||
|
||||
Options: -p --path PATH Path to files. |
||||
|
||||
""" |
||||
$ prog -p root |
||||
{"--path": "root"} |
||||
|
||||
$ prog --path root |
||||
{"--path": "root"} |
||||
|
||||
|
||||
r"""Usage: prog [options] |
||||
|
||||
Options: |
||||
-p PATH Path to files [default: ./] |
||||
|
||||
""" |
||||
$ prog |
||||
{"-p": "./"} |
||||
|
||||
$ prog -phome |
||||
{"-p": "home"} |
||||
|
||||
|
||||
r"""UsAgE: prog [options] |
||||
|
||||
OpTiOnS: --path=<files> Path to files |
||||
[dEfAuLt: /root] |
||||
|
||||
""" |
||||
$ prog |
||||
{"--path": "/root"} |
||||
|
||||
$ prog --path=home |
||||
{"--path": "home"} |
||||
|
||||
|
||||
r"""usage: prog [options] |
||||
|
||||
options: |
||||
-a Add |
||||
-r Remote |
||||
-m <msg> Message |
||||
|
||||
""" |
||||
$ prog -a -r -m Hello |
||||
{"-a": true, |
||||
"-r": true, |
||||
"-m": "Hello"} |
||||
|
||||
$ prog -armyourass |
||||
{"-a": true, |
||||
"-r": true, |
||||
"-m": "yourass"} |
||||
|
||||
$ prog -a -r |
||||
{"-a": true, |
||||
"-r": true, |
||||
"-m": null} |
||||
|
||||
|
||||
r"""Usage: prog [options] |
||||
|
||||
Options: --version |
||||
--verbose |
||||
|
||||
""" |
||||
$ prog --version |
||||
{"--version": true, |
||||
"--verbose": false} |
||||
|
||||
$ prog --verbose |
||||
{"--version": false, |
||||
"--verbose": true} |
||||
|
||||
$ prog --ver |
||||
"user-error" |
||||
|
||||
$ prog --verb |
||||
{"--version": false, |
||||
"--verbose": true} |
||||
|
||||
|
||||
r"""usage: prog [-a -r -m <msg>] |
||||
|
||||
options: |
||||
-a Add |
||||
-r Remote |
||||
-m <msg> Message |
||||
|
||||
""" |
||||
$ prog -armyourass |
||||
{"-a": true, |
||||
"-r": true, |
||||
"-m": "yourass"} |
||||
|
||||
|
||||
r"""usage: prog [-armmsg] |
||||
|
||||
options: -a Add |
||||
-r Remote |
||||
-m <msg> Message |
||||
|
||||
""" |
||||
$ prog -a -r -m Hello |
||||
{"-a": true, |
||||
"-r": true, |
||||
"-m": "Hello"} |
||||
|
||||
|
||||
r"""usage: prog -a -b |
||||
|
||||
options: |
||||
-a |
||||
-b |
||||
|
||||
""" |
||||
$ prog -a -b |
||||
{"-a": true, "-b": true} |
||||
|
||||
$ prog -b -a |
||||
{"-a": true, "-b": true} |
||||
|
||||
$ prog -a |
||||
"user-error" |
||||
|
||||
$ prog |
||||
"user-error" |
||||
|
||||
|
||||
r"""usage: prog (-a -b) |
||||
|
||||
options: -a |
||||
-b |
||||
|
||||
""" |
||||
$ prog -a -b |
||||
{"-a": true, "-b": true} |
||||
|
||||
$ prog -b -a |
||||
{"-a": true, "-b": true} |
||||
|
||||
$ prog -a |
||||
"user-error" |
||||
|
||||
$ prog |
||||
"user-error" |
||||
|
||||
|
||||
r"""usage: prog [-a] -b |
||||
|
||||
options: -a |
||||
-b |
||||
|
||||
""" |
||||
$ prog -a -b |
||||
{"-a": true, "-b": true} |
||||
|
||||
$ prog -b -a |
||||
{"-a": true, "-b": true} |
||||
|
||||
$ prog -a |
||||
"user-error" |
||||
|
||||
$ prog -b |
||||
{"-a": false, "-b": true} |
||||
|
||||
$ prog |
||||
"user-error" |
||||
|
||||
|
||||
r"""usage: prog [(-a -b)] |
||||
|
||||
options: -a |
||||
-b |
||||
|
||||
""" |
||||
$ prog -a -b |
||||
{"-a": true, "-b": true} |
||||
|
||||
$ prog -b -a |
||||
{"-a": true, "-b": true} |
||||
|
||||
$ prog -a |
||||
"user-error" |
||||
|
||||
$ prog -b |
||||
"user-error" |
||||
|
||||
$ prog |
||||
{"-a": false, "-b": false} |
||||
|
||||
|
||||
r"""usage: prog (-a|-b) |
||||
|
||||
options: -a |
||||
-b |
||||
|
||||
""" |
||||
$ prog -a -b |
||||
"user-error" |
||||
|
||||
$ prog |
||||
"user-error" |
||||
|
||||
$ prog -a |
||||
{"-a": true, "-b": false} |
||||
|
||||
$ prog -b |
||||
{"-a": false, "-b": true} |
||||
|
||||
|
||||
r"""usage: prog [ -a | -b ] |
||||
|
||||
options: -a |
||||
-b |
||||
|
||||
""" |
||||
$ prog -a -b |
||||
"user-error" |
||||
|
||||
$ prog |
||||
{"-a": false, "-b": false} |
||||
|
||||
$ prog -a |
||||
{"-a": true, "-b": false} |
||||
|
||||
$ prog -b |
||||
{"-a": false, "-b": true} |
||||
|
||||
|
||||
r"""usage: prog <arg>""" |
||||
$ prog 10 |
||||
{"<arg>": "10"} |
||||
|
||||
$ prog 10 20 |
||||
"user-error" |
||||
|
||||
$ prog |
||||
"user-error" |
||||
|
||||
|
||||
r"""usage: prog [<arg>]""" |
||||
$ prog 10 |
||||
{"<arg>": "10"} |
||||
|
||||
$ prog 10 20 |
||||
"user-error" |
||||
|
||||
$ prog |
||||
{"<arg>": null} |
||||
|
||||
|
||||
r"""usage: prog <kind> <name> <type>""" |
||||
$ prog 10 20 40 |
||||
{"<kind>": "10", "<name>": "20", "<type>": "40"} |
||||
|
||||
$ prog 10 20 |
||||
"user-error" |
||||
|
||||
$ prog |
||||
"user-error" |
||||
|
||||
|
||||
r"""usage: prog <kind> [<name> <type>]""" |
||||
$ prog 10 20 40 |
||||
{"<kind>": "10", "<name>": "20", "<type>": "40"} |
||||
|
||||
$ prog 10 20 |
||||
{"<kind>": "10", "<name>": "20", "<type>": null} |
||||
|
||||
$ prog |
||||
"user-error" |
||||
|
||||
|
||||
r"""usage: prog [<kind> | <name> <type>]""" |
||||
$ prog 10 20 40 |
||||
"user-error" |
||||
|
||||
$ prog 20 40 |
||||
{"<kind>": null, "<name>": "20", "<type>": "40"} |
||||
|
||||
$ prog |
||||
{"<kind>": null, "<name>": null, "<type>": null} |
||||
|
||||
|
||||
r"""usage: prog (<kind> --all | <name>) |
||||
|
||||
options: |
||||
--all |
||||
|
||||
""" |
||||
$ prog 10 --all |
||||
{"<kind>": "10", "--all": true, "<name>": null} |
||||
|
||||
$ prog 10 |
||||
{"<kind>": null, "--all": false, "<name>": "10"} |
||||
|
||||
$ prog |
||||
"user-error" |
||||
|
||||
|
||||
r"""usage: prog [<name> <name>]""" |
||||
$ prog 10 20 |
||||
{"<name>": ["10", "20"]} |
||||
|
||||
$ prog 10 |
||||
{"<name>": ["10"]} |
||||
|
||||
$ prog |
||||
{"<name>": []} |
||||
|
||||
|
||||
r"""usage: prog [(<name> <name>)]""" |
||||
$ prog 10 20 |
||||
{"<name>": ["10", "20"]} |
||||
|
||||
$ prog 10 |
||||
"user-error" |
||||
|
||||
$ prog |
||||
{"<name>": []} |
||||
|
||||
|
||||
r"""usage: prog NAME...""" |
||||
$ prog 10 20 |
||||
{"NAME": ["10", "20"]} |
||||
|
||||
$ prog 10 |
||||
{"NAME": ["10"]} |
||||
|
||||
$ prog |
||||
"user-error" |
||||
|
||||
|
||||
r"""usage: prog [NAME]...""" |
||||
$ prog 10 20 |
||||
{"NAME": ["10", "20"]} |
||||
|
||||
$ prog 10 |
||||
{"NAME": ["10"]} |
||||
|
||||
$ prog |
||||
{"NAME": []} |
||||
|
||||
|
||||
r"""usage: prog [NAME...]""" |
||||
$ prog 10 20 |
||||
{"NAME": ["10", "20"]} |
||||
|
||||
$ prog 10 |
||||
{"NAME": ["10"]} |
||||
|
||||
$ prog |
||||
{"NAME": []} |
||||
|
||||
|
||||
r"""usage: prog [NAME [NAME ...]]""" |
||||
$ prog 10 20 |
||||
{"NAME": ["10", "20"]} |
||||
|
||||
$ prog 10 |
||||
{"NAME": ["10"]} |
||||
|
||||
$ prog |
||||
{"NAME": []} |
||||
|
||||
|
||||
r"""usage: prog (NAME | --foo NAME) |
||||
|
||||
options: --foo |
||||
|
||||
""" |
||||
$ prog 10 |
||||
{"NAME": "10", "--foo": false} |
||||
|
||||
$ prog --foo 10 |
||||
{"NAME": "10", "--foo": true} |
||||
|
||||
$ prog --foo=10 |
||||
"user-error" |
||||
|
||||
|
||||
r"""usage: prog (NAME | --foo) [--bar | NAME] |
||||
|
||||
options: --foo |
||||
options: --bar |
||||
|
||||
""" |
||||
$ prog 10 |
||||
{"NAME": ["10"], "--foo": false, "--bar": false} |
||||
|
||||
$ prog 10 20 |
||||
{"NAME": ["10", "20"], "--foo": false, "--bar": false} |
||||
|
||||
$ prog --foo --bar |
||||
{"NAME": [], "--foo": true, "--bar": true} |
||||
|
||||
|
||||
r"""Naval Fate. |
||||
|
||||
Usage: |
||||
prog ship new <name>... |
||||
prog ship [<name>] move <x> <y> [--speed=<kn>] |
||||
prog ship shoot <x> <y> |
||||
prog mine (set|remove) <x> <y> [--moored|--drifting] |
||||
prog -h | --help |
||||
prog --version |
||||
|
||||
Options: |
||||
-h --help Show this screen. |
||||
--version Show version. |
||||
--speed=<kn> Speed in knots [default: 10]. |
||||
--moored Mored (anchored) mine. |
||||
--drifting Drifting mine. |
||||
|
||||
""" |
||||
$ prog ship Guardian move 150 300 --speed=20 |
||||
{"--drifting": false, |
||||
"--help": false, |
||||
"--moored": false, |
||||
"--speed": "20", |
||||
"--version": false, |
||||
"<name>": ["Guardian"], |
||||
"<x>": "150", |
||||
"<y>": "300", |
||||
"mine": false, |
||||
"move": true, |
||||
"new": false, |
||||
"remove": false, |
||||
"set": false, |
||||
"ship": true, |
||||
"shoot": false} |
||||
|
||||
|
||||
r"""usage: prog --hello""" |
||||
$ prog --hello |
||||
{"--hello": true} |
||||
|
||||
|
||||
r"""usage: prog [--hello=<world>]""" |
||||
$ prog |
||||
{"--hello": null} |
||||
|
||||
$ prog --hello wrld |
||||
{"--hello": "wrld"} |
||||
|
||||
|
||||
r"""usage: prog [-o]""" |
||||
$ prog |
||||
{"-o": false} |
||||
|
||||
$ prog -o |
||||
{"-o": true} |
||||
|
||||
|
||||
r"""usage: prog [-opr]""" |
||||
$ prog -op |
||||
{"-o": true, "-p": true, "-r": false} |
||||
|
||||
|
||||
r"""usage: prog --aabb | --aa""" |
||||
$ prog --aa |
||||
{"--aabb": false, "--aa": true} |
||||
|
||||
$ prog --a |
||||
"user-error" # not a unique prefix |
||||
|
||||
# |
||||
# Counting number of flags |
||||
# |
||||
|
||||
r"""Usage: prog -v""" |
||||
$ prog -v |
||||
{"-v": true} |
||||
|
||||
|
||||
r"""Usage: prog [-v -v]""" |
||||
$ prog |
||||
{"-v": 0} |
||||
|
||||
$ prog -v |
||||
{"-v": 1} |
||||
|
||||
$ prog -vv |
||||
{"-v": 2} |
||||
|
||||
|
||||
r"""Usage: prog -v ...""" |
||||
$ prog |
||||
"user-error" |
||||
|
||||
$ prog -v |
||||
{"-v": 1} |
||||
|
||||
$ prog -vv |
||||
{"-v": 2} |
||||
|
||||
$ prog -vvvvvv |
||||
{"-v": 6} |
||||
|
||||
|
||||
r"""Usage: prog [-v | -vv | -vvv] |
||||
|
||||
This one is probably most readable user-friednly variant. |
||||
|
||||
""" |
||||
$ prog |
||||
{"-v": 0} |
||||
|
||||
$ prog -v |
||||
{"-v": 1} |
||||
|
||||
$ prog -vv |
||||
{"-v": 2} |
||||
|
||||
$ prog -vvvv |
||||
"user-error" |
||||
|
||||
|
||||
r"""usage: prog [--ver --ver]""" |
||||
$ prog --ver --ver |
||||
{"--ver": 2} |
||||
|
||||
|
||||
# |
||||
# Counting commands |
||||
# |
||||
|
||||
r"""usage: prog [go]""" |
||||
$ prog go |
||||
{"go": true} |
||||
|
||||
|
||||
r"""usage: prog [go go]""" |
||||
$ prog |
||||
{"go": 0} |
||||
|
||||
$ prog go |
||||
{"go": 1} |
||||
|
||||
$ prog go go |
||||
{"go": 2} |
||||
|
||||
$ prog go go go |
||||
"user-error" |
||||
|
||||
r"""usage: prog go...""" |
||||
$ prog go go go go go |
||||
{"go": 5} |
||||
|
||||
# |
||||
# [options] does not include options from usage-pattern |
||||
# |
||||
r"""usage: prog [options] [-a] |
||||
|
||||
options: -a |
||||
-b |
||||
""" |
||||
$ prog -a |
||||
{"-a": true, "-b": false} |
||||
|
||||
$ prog -aa |
||||
"user-error" |
||||
|
||||
# |
||||
# Test [options] shourtcut |
||||
# |
||||
|
||||
r"""Usage: prog [options] A |
||||
Options: |
||||
-q Be quiet |
||||
-v Be verbose. |
||||
|
||||
""" |
||||
$ prog arg |
||||
{"A": "arg", "-v": false, "-q": false} |
||||
|
||||
$ prog -v arg |
||||
{"A": "arg", "-v": true, "-q": false} |
||||
|
||||
$ prog -q arg |
||||
{"A": "arg", "-v": false, "-q": true} |
||||
|
||||
# |
||||
# Test single dash |
||||
# |
||||
|
||||
r"""usage: prog [-]""" |
||||
|
||||
$ prog - |
||||
{"-": true} |
||||
|
||||
$ prog |
||||
{"-": false} |
||||
|
||||
# |
||||
# If argument is repeated, its value should always be a list |
||||
# |
||||
|
||||
r"""usage: prog [NAME [NAME ...]]""" |
||||
|
||||
$ prog a b |
||||
{"NAME": ["a", "b"]} |
||||
|
||||
$ prog |
||||
{"NAME": []} |
||||
|
||||
# |
||||
# Option's argument defaults to null/None |
||||
# |
||||
|
||||
r"""usage: prog [options] |
||||
options: |
||||
-a Add |
||||
-m <msg> Message |
||||
|
||||
""" |
||||
$ prog -a |
||||
{"-m": null, "-a": true} |
||||
|
||||
# |
||||
# Test options without description |
||||
# |
||||
|
||||
r"""usage: prog --hello""" |
||||
$ prog --hello |
||||
{"--hello": true} |
||||
|
||||
r"""usage: prog [--hello=<world>]""" |
||||
$ prog |
||||
{"--hello": null} |
||||
|
||||
$ prog --hello wrld |
||||
{"--hello": "wrld"} |
||||
|
||||
r"""usage: prog [-o]""" |
||||
$ prog |
||||
{"-o": false} |
||||
|
||||
$ prog -o |
||||
{"-o": true} |
||||
|
||||
r"""usage: prog [-opr]""" |
||||
$ prog -op |
||||
{"-o": true, "-p": true, "-r": false} |
||||
|
||||
r"""usage: git [-v | --verbose]""" |
||||
$ prog -v |
||||
{"-v": true, "--verbose": false} |
||||
|
||||
r"""usage: git remote [-v | --verbose]""" |
||||
$ prog remote -v |
||||
{"remote": true, "-v": true, "--verbose": false} |
||||
|
||||
# |
||||
# Test empty usage pattern |
||||
# |
||||
|
||||
r"""usage: prog""" |
||||
$ prog |
||||
{} |
||||
|
||||
r"""usage: prog |
||||
prog <a> <b> |
||||
""" |
||||
$ prog 1 2 |
||||
{"<a>": "1", "<b>": "2"} |
||||
|
||||
$ prog |
||||
{"<a>": null, "<b>": null} |
||||
|
||||
r"""usage: prog <a> <b> |
||||
prog |
||||
""" |
||||
$ prog |
||||
{"<a>": null, "<b>": null} |
||||
|
||||
# |
||||
# Option's argument should not capture default value from usage pattern |
||||
# |
||||
|
||||
r"""usage: prog [--file=<f>]""" |
||||
$ prog |
||||
{"--file": null} |
||||
|
||||
r"""usage: prog [--file=<f>] |
||||
|
||||
options: --file <a> |
||||
|
||||
""" |
||||
$ prog |
||||
{"--file": null} |
||||
|
||||
r"""Usage: prog [-a <host:port>] |
||||
|
||||
Options: -a, --address <host:port> TCP address [default: localhost:6283]. |
||||
|
||||
""" |
||||
$ prog |
||||
{"--address": "localhost:6283"} |
||||
|
||||
# |
||||
# If option with argument could be repeated, |
||||
# its arguments should be accumulated into a list |
||||
# |
||||
|
||||
r"""usage: prog --long=<arg> ...""" |
||||
|
||||
$ prog --long one |
||||
{"--long": ["one"]} |
||||
|
||||
$ prog --long one --long two |
||||
{"--long": ["one", "two"]} |
||||
|
||||
# |
||||
# Test multiple elements repeated at once |
||||
# |
||||
|
||||
r"""usage: prog (go <direction> --speed=<km/h>)...""" |
||||
$ prog go left --speed=5 go right --speed=9 |
||||
{"go": 2, "<direction>": ["left", "right"], "--speed": ["5", "9"]} |
||||
|
||||
# |
||||
# Required options should work with option shortcut |
||||
# |
||||
|
||||
r"""usage: prog [options] -a |
||||
|
||||
options: -a |
||||
|
||||
""" |
||||
$ prog -a |
||||
{"-a": true} |
||||
|
||||
# |
||||
# If option could be repeated its defaults should be split into a list |
||||
# |
||||
|
||||
r"""usage: prog [-o <o>]... |
||||
|
||||
options: -o <o> [default: x] |
||||
|
||||
""" |
||||
$ prog -o this -o that |
||||
{"-o": ["this", "that"]} |
||||
|
||||
$ prog |
||||
{"-o": ["x"]} |
||||
|
||||
r"""usage: prog [-o <o>]... |
||||
|
||||
options: -o <o> [default: x y] |
||||
|
||||
""" |
||||
$ prog -o this |
||||
{"-o": ["this"]} |
||||
|
||||
$ prog |
||||
{"-o": ["x", "y"]} |
||||
|
||||
# |
||||
# Test stacked option's argument |
||||
# |
||||
|
||||
r"""usage: prog -pPATH |
||||
|
||||
options: -p PATH |
||||
|
||||
""" |
||||
$ prog -pHOME |
||||
{"-p": "HOME"} |
||||
|
||||
# |
||||
# Issue 56: Repeated mutually exclusive args give nested lists sometimes |
||||
# |
||||
|
||||
r"""Usage: foo (--xx=x|--yy=y)...""" |
||||
$ prog --xx=1 --yy=2 |
||||
{"--xx": ["1"], "--yy": ["2"]} |
||||
|
||||
# |
||||
# POSIXly correct tokenization |
||||
# |
||||
|
||||
r"""usage: prog [<input file>]""" |
||||
$ prog f.txt |
||||
{"<input file>": "f.txt"} |
||||
|
||||
r"""usage: prog [--input=<file name>]...""" |
||||
$ prog --input a.txt --input=b.txt |
||||
{"--input": ["a.txt", "b.txt"]} |
||||
|
||||
# |
||||
# Issue 85: `[options]` shourtcut with multiple subcommands |
||||
# |
||||
|
||||
r"""usage: prog good [options] |
||||
prog fail [options] |
||||
|
||||
options: --loglevel=N |
||||
|
||||
""" |
||||
$ prog fail --loglevel 5 |
||||
{"--loglevel": "5", "fail": true, "good": false} |
||||
|
||||
# |
||||
# Usage-section syntax |
||||
# |
||||
|
||||
r"""usage:prog --foo""" |
||||
$ prog --foo |
||||
{"--foo": true} |
||||
|
||||
r"""PROGRAM USAGE: prog --foo""" |
||||
$ prog --foo |
||||
{"--foo": true} |
||||
|
||||
r"""Usage: prog --foo |
||||
prog --bar |
||||
NOT PART OF SECTION""" |
||||
$ prog --foo |
||||
{"--foo": true, "--bar": false} |
||||
|
||||
r"""Usage: |
||||
prog --foo |
||||
prog --bar |
||||
|
||||
NOT PART OF SECTION""" |
||||
$ prog --foo |
||||
{"--foo": true, "--bar": false} |
||||
|
||||
r"""Usage: |
||||
prog --foo |
||||
prog --bar |
||||
NOT PART OF SECTION""" |
||||
$ prog --foo |
||||
{"--foo": true, "--bar": false} |
||||
|
||||
# |
||||
# Options-section syntax |
||||
# |
||||
|
||||
r"""Usage: prog [options] |
||||
|
||||
global options: --foo |
||||
local options: --baz |
||||
--bar |
||||
other options: |
||||
--egg |
||||
--spam |
||||
-not-an-option- |
||||
|
||||
""" |
||||
$ prog --baz --egg |
||||
{"--foo": false, "--baz": true, "--bar": false, "--egg": true, "--spam": false} |
@ -1,14 +1,14 @@
|
||||
# common是必须的section |
||||
# [common] is integral section |
||||
[common] |
||||
server_addr = 127.0.0.1 |
||||
server_addr = 0.0.0.0 |
||||
server_port = 7000 |
||||
log_file = ./frpc.log |
||||
# console or real logFile path like ./frpc.log |
||||
log_file = console |
||||
# debug, info, warn, error |
||||
log_level = debug |
||||
# file, console |
||||
log_way = console |
||||
|
||||
# test1即为name |
||||
# test1 is the proxy name same as server's configuration |
||||
[test1] |
||||
passwd = 123 |
||||
local_ip = 127.0.0.1 |
||||
local_port = 22 |
||||
|
After Width: | Height: | Size: 10 KiB |
@ -0,0 +1,68 @@
|
||||
# Quick Start |
||||
|
||||
frp is easier to use compared with other similar projects. |
||||
|
||||
We will use a simple demo to demonstrate how to create a connection to server A's ssh port by server B with public IP address x.x.x.x(replace to the real IP address of your server). |
||||
|
||||
### Download SourceCode |
||||
|
||||
`go get github.com/fatedier/frp` is recommended, then the code will be copied to the directory `$GOPATH/src/github.com/fatedier/frp`. |
||||
|
||||
Or you can use `git clone https://github.com/fatedier/frp.git $GOPATH/src/github.com/fatedier/frp`. |
||||
|
||||
### Compile |
||||
|
||||
Enter the root directory and execute `make`, then wait until finished. |
||||
|
||||
**bin** include all executable programs when **conf** include corresponding configuration files. |
||||
|
||||
### Pre-requirement |
||||
|
||||
* Go environment. Version of go >= 1.4. |
||||
* Godep (if not exist, go get will be executed to download godep when compiling) |
||||
|
||||
### Deploy |
||||
|
||||
1. Move `./bin/frps` and `./conf/frps.ini` to any directory of server B. |
||||
2. Move `./bin/frpc` and `./conf/frpc.ini` to any directory of server A. |
||||
3. Modify all configuration files, details in next paragraph. |
||||
4. Execute `nohup ./frps &` or `nohup ./frps -c ./frps.ini &` in server B. |
||||
5. Execute `nohup ./frpc &` or `nohup ./frpc -c ./frpc.ini &` in server A. |
||||
6. Use `ssh -oPort=6000 {user}@x.x.x.x` to test if frp is work(replace {user} to real username in server A). |
||||
|
||||
### Configuration files |
||||
|
||||
#### frps.ini |
||||
|
||||
```ini |
||||
[common] |
||||
bind_addr = 0.0.0.0 |
||||
# for accept connections from frpc |
||||
bind_port = 7000 |
||||
log_file = ./frps.log |
||||
log_level = info |
||||
|
||||
# test is the custom name of proxy and there can be many proxies with unique name in one configure file |
||||
[test] |
||||
passwd = 123 |
||||
bind_addr = 0.0.0.0 |
||||
# finally we connect to server A by this port |
||||
listen_port = 6000 |
||||
``` |
||||
|
||||
#### frpc.ini |
||||
|
||||
```ini |
||||
[common] |
||||
# server address of frps |
||||
server_addr = x.x.x.x |
||||
server_port = 7000 |
||||
log_file = ./frpc.log |
||||
log_level = info |
||||
|
||||
# test is proxy name same with configure in frps.ini |
||||
[test] |
||||
passwd = 123 |
||||
# local port which need to be transferred |
||||
local_port = 22 |
||||
``` |
@ -0,0 +1,66 @@
|
||||
# frp 使用文档 |
||||
|
||||
frp 相比于其他项目而言非常易于部署和使用,这里我们用一个简单的示例演示如何通过一台拥有公网IP地址的服务器B,访问处于内网环境中的服务器A的ssh端口,服务器B的IP地址为 x.x.x.x(测试时替换为真实的IP地址)。 |
||||
|
||||
### 下载源码 |
||||
|
||||
推荐直接使用 `go get github.com/fatedier/frp` 下载源代码安装,执行命令后代码将会拷贝到 `$GOPATH/src/github.com/fatedier/frp` 目录下。 |
||||
|
||||
或者可以使用 `git clone https://github.com/fatedier/frp.git $GOPATH/src/github.com/fatedier/frp` 拷贝到相应目录下。 |
||||
|
||||
### 编译 |
||||
|
||||
进入下载后的源码根目录,执行 `make` 命令,等待编译完成。 |
||||
|
||||
编译完成后, **bin** 目录下是编译好的可执行文件,**conf** 目录下是示例配置文件。 |
||||
|
||||
### 依赖 |
||||
|
||||
* go 1.4 以上版本 |
||||
* godep (如果检查不存在,编译时会通过 go get 命令安装) |
||||
|
||||
### 部署 |
||||
|
||||
1. 将 ./bin/frps 和 ./conf/frps.ini 拷贝至服务器B任意目录。 |
||||
2. 将 ./bin/frpc 和 ./conf/frpc.ini 拷贝至服务器A任意目录。 |
||||
3. 修改两边的配置文件,见下一节说明。 |
||||
4. 在服务器B执行 `nohup ./frps &` 或者 `nohup ./frps -c ./frps.ini &`。 |
||||
5. 在服务器A执行 `nohup ./frpc &` 或者 `nohup ./frpc -c ./frpc.ini &`。 |
||||
6. 通过 `ssh -oPort=6000 {user}@x.x.x.x` 测试是否能够成功连接服务器A({user}替换为服务器A上存在的真实用户)。 |
||||
|
||||
### 配置文件 |
||||
|
||||
#### frps.ini |
||||
|
||||
```ini |
||||
[common] |
||||
bind_addr = 0.0.0.0 |
||||
# 用于接收 frpc 连接的端口 |
||||
bind_port = 7000 |
||||
log_file = ./frps.log |
||||
log_level = info |
||||
|
||||
# test 为代理的自定义名称,可以有多个,不能重复,和frpc中名称对应 |
||||
[test] |
||||
passwd = 123 |
||||
bind_addr = 0.0.0.0 |
||||
# 最后将通过此端口访问后端服务 |
||||
listen_port = 6000 |
||||
``` |
||||
|
||||
#### frpc.ini |
||||
|
||||
```ini |
||||
[common] |
||||
# frps 所在服务器绑定的IP地址 |
||||
server_addr = x.x.x.x |
||||
server_port = 7000 |
||||
log_file = ./frpc.log |
||||
log_level = info |
||||
|
||||
# test需要和 frps.ini 中配置一致 |
||||
[test] |
||||
passwd = 123 |
||||
# 需要转发的本地端口 |
||||
local_port = 22 |
||||
``` |
@ -0,0 +1,58 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package version |
||||
|
||||
import ( |
||||
"strconv" |
||||
"strings" |
||||
) |
||||
|
||||
var version string = "0.2.0" |
||||
|
||||
func Full() string { |
||||
return version |
||||
} |
||||
|
||||
func Proto(v string) int64 { |
||||
arr := strings.Split(v, ".") |
||||
if len(arr) < 2 { |
||||
return 0 |
||||
} |
||||
res, _ := strconv.ParseInt(arr[0], 10, 64) |
||||
return res |
||||
} |
||||
|
||||
func Major(v string) int64 { |
||||
arr := strings.Split(v, ".") |
||||
if len(arr) < 2 { |
||||
return 0 |
||||
} |
||||
res, _ := strconv.ParseInt(arr[1], 10, 64) |
||||
return res |
||||
} |
||||
|
||||
func Minor(v string) int64 { |
||||
arr := strings.Split(v, ".") |
||||
if len(arr) < 2 { |
||||
return 0 |
||||
} |
||||
res, _ := strconv.ParseInt(arr[2], 10, 64) |
||||
return res |
||||
} |
||||
|
||||
// add every case there if server will not accept client's protocol and return false
|
||||
func Compat(client string, server string) bool { |
||||
return true |
||||
} |
@ -0,0 +1,56 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package version |
||||
|
||||
import ( |
||||
"fmt" |
||||
"strconv" |
||||
"strings" |
||||
"testing" |
||||
) |
||||
|
||||
func TestFull(t *testing.T) { |
||||
version := Full() |
||||
arr := strings.Split(version, ".") |
||||
if len(arr) != 3 { |
||||
t.Fatalf("Version string error: %s", version) |
||||
} |
||||
|
||||
proto, err := strconv.ParseInt(arr[0], 10, 64) |
||||
if err != nil || proto < 0 { |
||||
t.Fatalf("Version proto error") |
||||
} |
||||
|
||||
major, err := strconv.ParseInt(arr[1], 10, 64) |
||||
if err != nil || major < 0 { |
||||
t.Fatalf("Version major error") |
||||
} |
||||
|
||||
minor, err := strconv.ParseInt(arr[2], 10, 64) |
||||
if err != nil || minor < 0 { |
||||
t.Fatalf("Version minor error") |
||||
} |
||||
} |
||||
|
||||
func TestVersion(t *testing.T) { |
||||
proto := Proto(Full()) |
||||
major := Major(Full()) |
||||
minor := Minor(Full()) |
||||
parseVerion := fmt.Sprintf("%d.%d.%d", proto, major, minor) |
||||
version := Full() |
||||
if parseVerion != version { |
||||
t.Fatalf("Get version incorrect, version [%s], parseVerion [%s]", version, parseVerion) |
||||
} |
||||
} |
Loading…
Reference in new issue