diff --git a/browser/browser.go b/browser/browser.go new file mode 100644 index 0000000..80c3afc --- /dev/null +++ b/browser/browser.go @@ -0,0 +1,50 @@ +// Copyright 2024 KusionStack Authors +// +// 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 browser + +import ( + "net/url" + "os/exec" + "runtime" + + "github.com/pkg/browser" +) + +// nativeBrowser should implement the Browser interface. +var _ Browser = nativeBrowser{} + +// NewNativeBrowser creates and returns a Browser that will attempt to interact +// with the browser-launching mechanisms of the operating system where the +// program is currently running. +func NewNativeBrowser() Browser { + return nativeBrowser{} +} + +type nativeBrowser struct{} + +// OpenURL opens given url in a new browser tab. +func (b nativeBrowser) OpenURL(urlstr string) error { + _, err := url.Parse(urlstr) + if err != nil { + return err + } + if runtime.GOOS == "linux" { + _, err = exec.LookPath("xdg-open") + if err != nil { + return nil + } + } + return browser.OpenURL(urlstr) +} diff --git a/browser/browser_test.go b/browser/browser_test.go new file mode 100644 index 0000000..6a989f2 --- /dev/null +++ b/browser/browser_test.go @@ -0,0 +1,25 @@ +// Copyright 2024 KusionStack Authors +// +// 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 browser + +import "testing" + +func TestOpenInvalidURL(t *testing.T) { + browser := NewNativeBrowser() + err := browser.OpenURL("ht%2ds://localhost:8080") + if err == nil { + t.Fatal("should return invalid url error") + } +} diff --git a/browser/doc.go b/browser/doc.go new file mode 100644 index 0000000..f914729 --- /dev/null +++ b/browser/doc.go @@ -0,0 +1,16 @@ +// Copyright 2024 KusionStack Authors +// +// 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 browser provides utility to open a given url in web browser. +package browser diff --git a/browser/interface.go b/browser/interface.go new file mode 100644 index 0000000..5f2cb5e --- /dev/null +++ b/browser/interface.go @@ -0,0 +1,29 @@ +// Copyright 2024 KusionStack Authors +// +// 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 browser + +// Browser is an object that knows how to open a given URL in a new tab in +// some suitable browser on the current system. +type Browser interface { + // OpenURL opens the given URL in a web browser. + // + // Depending on the circumstances and on the target platform, this may or + // may not cause the browser to take input focus. Because of this + // uncertainty, any caller of this method must be sure to include some + // language in its UI output to let the user know that a browser tab has + // opened somewhere, so that they can go and find it if the focus didn't + // switch automatically. + OpenURL(url string) error +} diff --git a/go.mod b/go.mod index 720a566..8a87b43 100644 --- a/go.mod +++ b/go.mod @@ -3,13 +3,15 @@ module kusionstack.io/component-base go 1.22.1 require ( + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c github.com/spf13/cobra v1.8.0 + github.com/spf13/pflag v1.0.5 go.uber.org/zap v1.27.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 ) require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect go.uber.org/multierr v1.10.0 // indirect + golang.org/x/sys v0.1.0 // indirect ) diff --git a/go.sum b/go.sum index e4d5f14..171b802 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -18,6 +20,8 @@ go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=