rq

package module
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 10, 2023 License: MIT Imports: 14 Imported by: 1

README

rq

Go library for making http requests from .http files.

Installation

go get github.com/go-rq/rq

.http File Syntax

### <name of request>
< {% <pre-request
javascipt> %} 

<method> <url>
<header>:<value>
...

<request body>

< {% <post-request 
javascript> %}
Scripts

Scripts can be embedded in the .http request directly or loaded from

### <name of request>
< path/to/script.js

<method> <url>
<header>:<value>
...

<request body>

< path/to/script.js
Scripting API
setEnv(key string, value string)

The runtime environment variables can be modified from either pre or post request script. No return value.

setEnv('host', 'http://localhost:8000');
getEnv(key string)

Returns the value of the environment variable key.

getEnv('host'); // returns 'http://localhost:8000'
assert(condition boolean, message string)

Some assertion which resolves to a boolean value can be made for the condition with a corresponding message. Each assertion is extracted from the scripting runtime and added to the Response object.

assert(response.status === 200, 'response code is 200');
log(message string)

Appends a log message to Request.Logs property allowing the go runtime to access debug information from the scripting runtime.

log(`the response status code was ${response.statusCode}`);
request and response objects

The response object is available in the post-request script and the request object is available in both the pre and post-request scripts. Changes made to these objects are not reflected in the actual request or response, rather they are used for assertions, control flow, and setting up the environment. There are a few exceptions to this rule, such as the skip property on request, see the next section for more information.

request = {
    name: 'Create A User',
    method: 'POST',
    url: 'http://localhost:8000/users',
    headers: {
      'Content-Type': 'application/json',
    }, 
    body: `{
        name: 'r2d2'
    }`,
}
response = {
    status: 'OK',
    statusCode: 200,
    headers: {
        'Content-Type': 'application/json',
    },
    body: `{
        id: '1234',
        name: 'r2d2'
    }`,

    // `json` is the parsed json body that is only available if the response Content-Type
    // header contains `application/json`
    json: {
      id: '1234',
      name: 'r2d2'
    } 
}
Skipping Requests (pre-request script)

You can prevent the request from being made from pre-request scripts being setting the skip property on the request object to true

Examples
### Create a User
< {% 
    setEnv('host', 'http://localhost:8000');
    setEnv('name', 'r2d2');
%}
POST {{host}}/users
Content-Type: application/json

{
    "name": "{{name}}"
}

< {% 
    assertTrue(response.status === 200, 'response code is 200');
%}
Running .http Files from Go Tests

The package treqs, short for Testing Requests, provides functions for running .http files from Go tests.

package test

import (
  "testing"

  "github.com/go-rq/rq/treqs"
)

func TestFoo(t *testing.T) {
    ctx := rq.WithEnvironment(context.Background(), 
    map[string]string{"host": "http://localhost:8080"}) 

    // run all requests in testdata/foo.http
    treqs.RunFile(t, ctx, "testdata/foo.http")
  
    // run all requests in all .http files in the testdata directory
    treqs.RunDir(t, ctx, "testdata")
}

Documentation

Index

Examples

Constants

View Source
const (
	RequestSeparator = "###"
)

Variables

View Source
var (
	ErrInvalidRequest = errors.New("invalid request")
	ErrSkipped        = errors.New("request skipped")
)

Functions

func GetEnvironment added in v0.4.0

func GetEnvironment(ctx context.Context) map[string]string

func ResetEnvironment

func ResetEnvironment(ctx context.Context)

func WithEnvironment

func WithEnvironment(ctx context.Context, env map[string]string) context.Context

func WithLogger added in v0.4.0

func WithLogger(ctx context.Context, logger Logger) context.Context

WithLogger returns a new context with the given logger. When a request is executed, the logger is used to log out the pre-request and post-request script logs

func WithRequestRunner

func WithRequestRunner(ctx context.Context, runner RequestRunner) context.Context

func WithRuntime

func WithRuntime(ctx context.Context, rt *Runtime) context.Context

Types

type Assertion

type Assertion struct {
	Message string `json:"message"`
	Success bool   `json:"success"`
}
type Header struct {
	Key   string
	Value string
}

type Headers

type Headers []Header

type Logger added in v0.4.0

type Logger interface {
	Log(...any)
}

Logger is the interface that wraps Log method. Log entries made in the pre-request and post-request scripts are passed to the Log method.

type Request

type Request struct {
	// The name of the request
	// Example: Get User
	Name string

	// PreRequestScript is a piece of JavaScript code that executes before the request is sent.
	// Example: var token = req.environment.get("token");
	PreRequestScript string

	// PreRequestAssertions is a list resulting from the assertions that were executed before the request is sent.
	PreRequestAssertions []Assertion

	// PostRequestScript is a piece of JavaScript code that executes after the request is sent.
	PostRequestScript string

	// The HTTP method used (GET, POST, PUT, DELETE, etc.)
	Method string

	// The URL of the request
	URL string
	// The HTTP body
	// Note: The body is not parsed.
	// Example: {"foo":"bar"}
	// Example: <xml><foo>bar</foo></xml>
	// Example: foo=bar&baz=qux
	Body string

	// The http Headers
	Headers Headers

	// Skip is a flag that indicates if the request should be skipped
	Skip bool

	// Logs is a list of logs generated by any scripts in the request
	Logs []string
}

Request is a struct that holds the HTTP request data.

Example
mux := http.NewServeMux()
mux.HandleFunc("/users", func(w http.ResponseWriter, _ *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	_ = json.NewEncoder(w).Encode(map[string]string{
		"userId": "1234",
	})
})
srv := httptest.NewServer(mux)
defer srv.Close()
input := `### Get User

  < {% 
    if(!getEnv('host')) {
      request.skip = true;
    }
  %}

  POST http://{{host}}/users
  Accept: application/json

  {
    "name": "Fred Flintstone"
  }

  < {%
    assert(response.statusCode === 201, 'status code is 201 Created')
    assert(response.json.userId != undefined, 'a user id is returned')
  %}
  `

reqs, err := ParseRequests(input)
if err != nil {
	panic(err)
}

result, err := reqs[0].Do(WithEnvironment(context.Background(), map[string]string{
	"host": srv.URL,
}))
if err != nil {
	panic(err)
}

fmt.Println(result.String())
Output:

func ParseFromFile

func ParseFromFile(path string) ([]Request, error)

func ParseRequests

func ParseRequests(input string) ([]Request, error)

func (Request) ApplyEnv added in v0.3.0

func (r Request) ApplyEnv(ctx context.Context) Request

func (Request) DisplayName

func (r Request) DisplayName() string

func (*Request) Do

func (r *Request) Do(ctx context.Context) (*Response, error)

func (Request) HttpText

func (r Request) HttpText() string

func (Request) String

func (r Request) String() string

func (Request) ToHttpRequest added in v0.3.0

func (r Request) ToHttpRequest(ctx context.Context) (*http.Request, error)

type RequestRunner

type RequestRunner interface {
	Do(req *http.Request) (*http.Response, error)
}

type Response

type Response struct {
	*http.Response

	PostRequestAssertions []Assertion
}

func (*Response) PrettyString

func (resp *Response) PrettyString() (string, error)

func (*Response) Raw

func (resp *Response) Raw() *http.Response

func (*Response) String

func (resp *Response) String() string

type Runtime

type Runtime struct {
	// contains filtered or unexported fields
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL