Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement bind argument #266

Merged
merged 1 commit into from
Apr 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,15 @@ To configure `qrcp` you can create a configuration file inside `$XDG_CONFIG_HOME
| Key | Type | Notes |
|-------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `interface` | String | This value is automatically discovered during the first launch of `qrcp`, you can set it to override the default. You can use the `any` interface to bind the web server to `0.0.0.0`. |
| `bind` | String | This value is used by qrcp to bind the web server to. Note: if this value is set, the `interface` parameter is ignored. |
| `port` | Integer | When this value is not set, `qrcp` will pick a random port at any launch. |
| `path` | String | When this value is not set, `qrcp` will add a random string at the end of URL. |
| `output` | String | Default directory to receive files to. If empty, the current working directory is used. |
| `fqdn` | String | When this value is set, `qrcp` will use it to replace the IP address in the generated URL. |
| `keepAlive` | Bool | Controls whether `qrcp` should quit after transferring the file. Defaults to `false`. |
| `secure` | Bool | Controls whether `qrcp` should use HTTPS instead of HTTP. Defaults to `false` |
| `tls-cert` | String | Path to the TLS certificate. It's only used when `secure: true`. |
| `tls-key` | String | Path to the TLS key. It's only used when `secure: true`. |
| `path` | String | When this value is not set, `qrcp` will add a random string at the end of URL. |
| `output` | String | Default directory to receive files to. If empty, the current working directory is used. |
| `fqdn` | String | When this value is set, `qrcp` will use it to replace the IP address in the generated URL. |
| `keepAlive` | Bool | Controls whether `qrcp` should quit after transferring the file. Defaults to `false`. |
| `secure` | Bool | Controls whether `qrcp` should use HTTPS instead of HTTP. Defaults to `false` |
| `tls-cert` | String | Path to the TLS certificate. It's only used when `secure: true`. |
| `tls-key` | String | Path to the TLS key. It's only used when `secure: true`. |


All the configuration parameters can be controlled via environment variables prefixed with `QRCP_`, for example:
Expand Down Expand Up @@ -281,6 +282,13 @@ This is useful when you want to transfer files from your Amazon EC2, Digital Oce
qrcp -i any MyDocument.pdf
```

### Bind

Alternatively to choosing the interface, you can directly specify the address you want `qrcp` to bind the webserver to.

```sh
qrcp --bind 10.20.30.40 MyDocument.pdf
```

### URL

Expand Down
1 change: 1 addition & 0 deletions application/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type Flags struct {
Port int
Path string
Interface string
Bind string
FQDN string
Zip bool
Config string
Expand Down
1 change: 1 addition & 0 deletions cmd/qrcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func init() {
rootCmd.PersistentFlags().IntVarP(&app.Flags.Port, "port", "p", 0, "port to use for the server")
rootCmd.PersistentFlags().StringVar(&app.Flags.Path, "path", "", "path to use. Defaults to a random string")
rootCmd.PersistentFlags().StringVarP(&app.Flags.Interface, "interface", "i", "", "network interface to use for the server")
rootCmd.PersistentFlags().StringVar(&app.Flags.Bind, "bind", "", "address to bind the web server to")
rootCmd.PersistentFlags().StringVarP(&app.Flags.FQDN, "fqdn", "d", "", "fully-qualified domain name to use for the resulting URLs")
rootCmd.PersistentFlags().BoolVarP(&app.Flags.Zip, "zip", "z", false, "zip content before transferring")
rootCmd.PersistentFlags().StringVarP(&app.Flags.Config, "config", "c", "", "path to the config file, defaults to $XDG_CONFIG_HOME/qrcp/config.json")
Expand Down
31 changes: 25 additions & 6 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
type Config struct {
Interface string `yaml:",omitempty"`
Port int `yaml:",omitempty"`
Bind string `yaml:",omitempty"`
KeepAlive bool `yaml:",omitempty"`
Path string `yaml:",omitempty"`
Secure bool `yaml:",omitempty"`
Expand Down Expand Up @@ -51,6 +52,7 @@ func New(app application.App) Config {
}
// Load file
cfg.Interface = v.GetString("interface")
cfg.Bind = v.GetString("bind")
cfg.Port = v.GetInt("port")
cfg.KeepAlive = v.GetBool("keepAlive")
cfg.Path = v.GetString("path")
Expand All @@ -64,33 +66,30 @@ func New(app application.App) Config {
if app.Flags.Interface != "" {
cfg.Interface = app.Flags.Interface
}
if app.Flags.Bind != "" {
cfg.Bind = app.Flags.Bind
}
if app.Flags.Port != 0 {
cfg.Port = app.Flags.Port
}
if app.Flags.KeepAlive {
cfg.KeepAlive = true
}

if app.Flags.Path != "" {
cfg.Path = app.Flags.Path
}

if app.Flags.Secure {
cfg.Secure = true
}

if app.Flags.TlsKey != "" {
cfg.TlsKey = app.Flags.TlsKey
}

if app.Flags.TlsCert != "" {
cfg.TlsCert = app.Flags.TlsCert
}

if app.Flags.FQDN != "" {
cfg.FQDN = app.Flags.FQDN
}

if app.Flags.Output != "" {
cfg.Output = app.Flags.Output
}
Expand Down Expand Up @@ -151,6 +150,26 @@ func Wizard(app application.App) error {
if err := v.WriteConfig(); err != nil {
panic(err)
}
// Ask for bind address
validateBind := func(input string) error {
if input == "" {
return nil
}
if !govalidator.IsIPv4(input) {
return errors.New("invalid address")
}
return nil
}
promptBind := promptui.Prompt{
Validate: validateBind,
Label: "Enter bind address (this will override the chosen interface address)",
Default: cfg.Bind,
}
if promptBindResultString, err := promptBind.Run(); err == nil {
if promptBindResultString != "" {
v.Set("bind", promptBindResultString)
}
}
// Ask for port
validatePort := func(input string) error {
_, err := strconv.ParseUint(input, 10, 16)
Expand Down
2 changes: 2 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ func TestNew(t *testing.T) {
Interface: "wlo1",
Port: 18080,
KeepAlive: false,
Bind: "10.20.30.40",
Path: "random",
Secure: false,
TlsKey: "/path/to/key",
Expand All @@ -106,6 +107,7 @@ func TestNew(t *testing.T) {
Config{
Interface: "wlo1",
Port: 99999,
Bind: "10.20.30.40",
KeepAlive: false,
Path: "random",
Secure: false,
Expand Down
1 change: 1 addition & 0 deletions config/testdata/full.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
interface: wlo1
port: 18080
bind: '10.20.30.40'
keepAlive: false
path: random
secure: false
Expand Down
6 changes: 5 additions & 1 deletion server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,15 @@ func (s Server) Shutdown() {
func New(cfg *config.Config) (*Server, error) {

app := &Server{}
// Get the address of the configured interface to bind the server to
// Get the address of the configured interface to bind the server to.
// If `bind` configuration parameter has been configured, it takes precedence
bind, err := util.GetInterfaceAddress(cfg.Interface)
if err != nil {
return &Server{}, err
}
if cfg.Bind != "" {
bind = cfg.Bind
}
// Create a listener. If `port: 0`, a random one is chosen
listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", bind, cfg.Port))
if err != nil {
Expand Down