184 lines
3.5 KiB
Go
184 lines
3.5 KiB
Go
package webdriver
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"os/exec"
|
|
"strconv"
|
|
)
|
|
|
|
type Driver struct {
|
|
server *exec.Cmd
|
|
|
|
host string
|
|
port uint16
|
|
sessionID string
|
|
}
|
|
|
|
func NewDriver() (*Driver, error) {
|
|
host := "127.0.0.1"
|
|
port := uint16(4444)
|
|
|
|
ctx := context.Background()
|
|
server := exec.CommandContext(ctx, "geckodriver", "--host", host, "--port", strconv.Itoa(int(port)))
|
|
|
|
stdout, err := server.StdoutPipe()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := server.Start(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scanner := bufio.NewScanner(stdout)
|
|
scanner.Scan()
|
|
|
|
return &Driver{
|
|
server: server,
|
|
host: host,
|
|
port: port,
|
|
}, nil
|
|
}
|
|
|
|
func UseDriver(host string, port uint16) *Driver {
|
|
return &Driver{
|
|
host: host,
|
|
port: port,
|
|
}
|
|
}
|
|
|
|
func (d *Driver) Close() error {
|
|
if d.server == nil {
|
|
return nil
|
|
}
|
|
|
|
if d.sessionID != "" {
|
|
if err := d.CloseSession(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if err := d.server.Cancel(); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := d.server.Wait(); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (d *Driver) buildSessionUrl(path string) string {
|
|
uri, err := url.JoinPath(fmt.Sprintf("http://%s:%d/session/%s", d.host, d.port, d.sessionID), path)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return uri
|
|
}
|
|
|
|
func (d *Driver) buildUrl(path string) string {
|
|
uri, err := url.JoinPath(fmt.Sprintf("http://%s:%d", d.host, d.port), path)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return uri
|
|
}
|
|
|
|
func (d *Driver) DoRawSessionRequest(method string, path string, body io.Reader) (*http.Response, error) {
|
|
req, err := http.NewRequest(method, d.buildSessionUrl(path), body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
req.Header.Add("Content-Type", "application/json")
|
|
|
|
return http.DefaultClient.Do(req)
|
|
}
|
|
|
|
func (d *Driver) DoRawRequest(method string, path string, body io.Reader) (*http.Response, error) {
|
|
req, err := http.NewRequest(method, d.buildUrl(path), body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
req.Header.Add("Content-Type", "application/json")
|
|
|
|
return http.DefaultClient.Do(req)
|
|
}
|
|
|
|
func (d *Driver) DoSessionRequest(method string, path string, body map[string]interface{}) (map[string]interface{}, error) {
|
|
if body == nil {
|
|
body = map[string]interface{}{}
|
|
}
|
|
|
|
data, err := json.Marshal(body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
resp, err := d.DoRawSessionRequest(method, path, bytes.NewReader(data))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
respBody := map[string]interface{}{}
|
|
if err := json.NewDecoder(resp.Body).Decode(&respBody); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return respBody, nil
|
|
}
|
|
|
|
func (d *Driver) DoRequest(method string, path string, body map[string]interface{}) (map[string]interface{}, error) {
|
|
if body == nil {
|
|
body = map[string]interface{}{}
|
|
}
|
|
|
|
data, err := json.Marshal(body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
resp, err := d.DoRawRequest(method, path, bytes.NewReader(data))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
respBody := map[string]interface{}{}
|
|
if err := json.NewDecoder(resp.Body).Decode(&respBody); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return respBody, nil
|
|
}
|
|
|
|
func (d *Driver) NewSession() error {
|
|
data, err := d.DoRequest(http.MethodPost, "/session", nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
d.sessionID = data["value"].(map[string]interface{})["sessionId"].(string)
|
|
return nil
|
|
}
|
|
|
|
func (d *Driver) CloseSession() error {
|
|
_, err := d.DoSessionRequest(http.MethodDelete, "", nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
d.sessionID = ""
|
|
return nil
|
|
}
|