Giter VIP home page Giter VIP logo

restish's Introduction

Restish Logo

Works With Restish User Guide CI codecov Docs Go Report Card

Restish is a CLI for interacting with REST-ish HTTP APIs with some nice features built-in โ€” like always having the latest API resources, fields, and operations available when they go live on the API without needing to install or update anything. Check out how Restish compares to cURL & HTTPie.

See the user guide for how to install Restish and get started.

Features include:

  • HTTP/2 (RFC 7540) with TLS by default with fallback to HTTP/1.1
  • Generic head/get/post/put/patch/delete verbs like curl or HTTPie
  • Generated commands for CLI operations, e.g. restish my-api list-users
    • Automatically discovers API descriptions
    • Supported formats
    • Automatic configuration of API auth if advertised by the API
    • Shell command completion for Bash, Fish, Zsh, Powershell
  • Automatic pagination of resource collections via RFC 5988 prev and next hypermedia links
  • API endpoint-based auth built-in with support for profiles:
    • HTTP Basic
    • API key via header or query param
    • OAuth2 client credentials flow (machine-to-machine, RFC 6749)
    • OAuth2 authorization code (with PKCE RFC 7636) flow
    • On the fly authorization through external tools for custom API signature mechanisms
  • Content negotiation, decoding & unmarshalling built-in:
  • Automatic retries with support for Retry-After and X-Retry-In headers when APIs are rate-limited.
  • Standardized hypermedia parsing into queryable/followable response links:
  • Local caching that respects RFC 7234 Cache-Control and Expires headers
  • CLI shorthand for structured data input (e.g. for JSON)
  • Shorthand query response filtering & projection
  • Colorized prettified readable output
  • Fast native zero-dependency binary

Articles:

This project started life as a fork of OpenAPI CLI Generator.

restish's People

Contributors

afh avatar cbliard avatar cgardens avatar csm-thu avatar danielgtaylor avatar dependabot[bot] avatar eddiemonge avatar exo-cedric avatar h0x91b-wix avatar james-maloney avatar kpayson avatar kpetremann avatar lalmeras avatar lgarrett-isp avatar lllibailll avatar martyhub avatar metadatadriven avatar mgagliardo91 avatar mterron avatar pyr avatar r4um avatar rburte-isp avatar tracam avatar waldyrious avatar wdullaer avatar zak905 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

restish's Issues

OpenAPI spec with circular references

Hi,
using restish with an OpenAPI spec that contains circular $refs causes to eat up all memory and finally be terminated by the os:

[       [1]    21027 killed     restish api configure example.

Here is a minimal example spec that fails:

openapi: 3.0.0
info:
  description: example API
  title: Exampe API
  version: 0.0.1
servers:
  - url: 'http://openapi_server:9000'
paths:
  /search:
    get:
      operationId: search
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/search_paths'
      summary: Search deeply for matching stuff
components:
  schemas:
    search_paths:
      type: object
      properties:
        paths:
          type: array
          items:
            $ref: '#/components/schemas/search_paths'
          description: Paths to matching stuff

inconsistent usage of flags

Running restish against https://petstore3.swagger.io/api/v3/openapi.json gives me the following endpoint usage message:

Usage:
  restish petstore find-pets-by-status [flags]

Aliases:
  find-pets-by-status, findpetsbystatus

Flags:
  -h, --help            help for find-pets-by-status
      --status string   Status values that need to be considered for filter (default "available")

Running restish petstore findpetsbystatus --status available yields

HTTP/2.0 400 Bad Request

while restish petstore findpetsbystatus -q status=available yields the expected response.

So the flag --status seems not to work as expected as described in the usage message.

But it works with restish petstore findpetsbytags --tags animal although it has a similar usage:

Usage:
  restish petstore findpetsbytags [flags]

Flags:
  -h, --help           help for findpetsbytags
      --tags strings   Tags to filter by

"Unexpected Escape Sequence" when using menu with arrow keys

While using the api configure menus, the arrow keys cause an error. I can select menu options buy starting to type the text for the option.

% restish api configure example
? Base URI http://example.org
Setting up a `default` profile
? Select option for profile `default`  [Use arrows to move, type to filter]
> Add header
  Add query param
  Setup auth
  Finished with profile
ERROR: Caught error: Unexpected Escape Sequence: ['\x1b' 'O']

I'm using the regular terminal emulator on MacOS with zsh

Trouble with Restish post syntax for arrays

I'm having trouble with the Restish syntax with arrays in the post params.

This is what my command looks like:

restish a-ci email-controller-send-email 1 from: "[email protected]", subject: "Restish is Great", html: "Wow", to[]:"[email protected]"

I get the error: no matches found: to[]:[email protected]

How do I create this post body
{
from:'[email protected]',
to:['[email protected]']
subject:'Restish is Great'
html:'Wow'
}

note: the 'to' field needs to be an array since that is the way it is described in the schema for the email object

  `"to": {
      "type": "array",
      "items": {
          "type": "string",
          "format": "idn-email"
      }
  },`

Bug: call of reflect.Value.Elem on zero Value with OpenAPI `anyOf`

Hi,

Thanks for restish, I'm starting to be a fan :)

But when using OpenAPI I got an issue when "anyOf" is present,

Consider this specification:

{
  "openapi": "3.0.2",
  "info": {
    "title": "FastAPI",
    "version": "0.1.0"
  },
  "paths": {
    "/": {
      "get": {
        "summary": "Root",
        "operationId": "root__get",
        "parameters": [
          {
            "required": false,
            "schema": {
              "title": "When",
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "string",
                  "format": "date"
                }
              ]
            },
            "name": "when",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "HTTPValidationError": {
        "title": "HTTPValidationError",
        "type": "object",
        "properties": {
          "detail": {
            "title": "Detail",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            }
          }
        }
      },
      "ValidationError": {
        "title": "ValidationError",
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "type": "object",
        "properties": {
          "loc": {
            "title": "Location",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "msg": {
            "title": "Message",
            "type": "string"
          },
          "type": {
            "title": "Error Type",
            "type": "string"
          }
        }
      }
    }
  }
}

Restish returns

DEBUG: Adding TLS configuration
DEBUG: Unmarshalling from application/json
DEBUG: Checking http://localhost:8000/openapi.json
DEBUG: Configuration: map[app-name:restish config-directory:/home/ahmet/.restish rsh-ca-cert: rsh-client-cert: rsh-client-key: rsh-filter: rsh-header:[] rsh-insecure:false rsh-no-cache:false rsh-no-paginate:false rsh-output-format:auto rsh-profile:default rsh-query:[] rsh-raw:false rsh-server: rsh-table:false rsh-verbose:true server-index:0]
ERROR: Caught error: reflect: call of reflect.Value.Elem on zero Value
DEBUG: goroutine 1 [running]:
runtime/debug.Stack(0xdc3a03, 0x10, 0xc00011f6b0)
	/home/ahmet/bin/gosrc/1.16/src/runtime/debug/stack.go:24 +0x9f
github.com/danielgtaylor/restish/cli.Run.func1()
	/home/ahmet/workspaces/golang/pkg/mod/github.com/danielgtaylor/[email protected]/cli/cli.go:510 +0x98
panic(0xcc7260, 0xc00000fbc0)
	/home/ahmet/bin/gosrc/1.16/src/runtime/panic.go:965 +0x1b9
reflect.Value.Elem(0x0, 0x0, 0x0, 0x4, 0xc000279048, 0xc00027a680)
	/home/ahmet/bin/gosrc/1.16/src/reflect/value.go:843 +0x1a5
github.com/danielgtaylor/restish/cli.Operation.command.func1(0xc00026d180, 0xc000781e90, 0x0, 0x1)
	/home/ahmet/workspaces/golang/pkg/mod/github.com/danielgtaylor/[email protected]/cli/operation.go:80 +0x3dc
github.com/spf13/cobra.(*Command).execute(0xc00026d180, 0xc000781e80, 0x1, 0x1, 0xc00026d180, 0xc000781e80)
	/home/ahmet/workspaces/golang/pkg/mod/github.com/spf13/[email protected]/command.go:860 +0x2c2
github.com/spf13/cobra.(*Command).ExecuteC(0xc00023d180, 0x1d, 0xc00026d400, 0xc000382c38)
	/home/ahmet/workspaces/golang/pkg/mod/github.com/spf13/[email protected]/command.go:974 +0x375
github.com/spf13/cobra.(*Command).Execute(...)
	/home/ahmet/workspaces/golang/pkg/mod/github.com/spf13/[email protected]/command.go:902
github.com/danielgtaylor/restish/cli.Run()
	/home/ahmet/workspaces/golang/pkg/mod/github.com/danielgtaylor/[email protected]/cli/cli.go:513 +0x593
main.main()
	/home/ahmet/workspaces/golang/pkg/mod/github.com/danielgtaylor/[email protected]/main.go:27 +0x177

OpenAPI was generated by FastAPI

import datetime
from typing import Union

from fastapi import FastAPI

app = FastAPI()


@app.get("/")
async def root(when: Union[str, datetime.date] = None):
    return {"when": when}

Not using OpenAPI v2 json spec

My api is using a json openapi v2 spec hosted at /openapi.json. When I configure it there is no error and I see in the server logs that both /openapi.yaml and /openapi.json are requested. But when I try restish example --help or anything else I get the below error and in the server log I see that only the yaml is requested.

% restish example --help
panic: could not detect API type: http://localhost:8080/

goroutine 1 [running]:
github.com/danielgtaylor/restish/cli.Run()
	/home/runner/work/restish/restish/cli/cli.go:447 +0x777
main.main()
	/home/runner/work/restish/restish/main.go:27 +0x177

I installed using homebrew.

Empty query param added when defined as array

With the following config for a GET req query parameter, an empty type param is added by default. Such as a trailing ?type= on the URL with the following example.

        "parameters": [
          {
            "name": "type",
            "in": "query",
            "description": "Filter by transaction type",
            "required": false,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "coinbase",
                  "token_transfer",
                  "smart_contract",
                  "contract_call",
                  "poison_microblock"
                ]
              }
            }
          },

Expected behaviour
No param should be added unless a value is defined.

Weird indentation for single object list

There is a bug in the shorthand rendering of simple lists/items:

$ restish :8000/v1/notes
HTTP/1.1 200 OK
Content-Length: 65
Content-Type: application/json; charset=utf-8
Date: Wed, 12 Aug 2020 19:50:48 GMT

[{
    created: "2020-08-12T12:50:44.681241-07:00"
    id: "test-note"
  }]

It should look like:

[{
  created: "2020-08-12T12:50:44.681241-07:00"
  id: "test-note"
}]

Version 0.11.0 stop working

I upgraded to 0.11.0 version and now I get this error every time I want to run restish command

ERROR: Caught error: yaml: unmarshal errors:
line 1: cannot unmarshal !!seq into map[string]interface {}

document query string parameters in -h usage docs

I've specified query string parameters in my openapi document:

 /jobs/{id}/results:
    get:
      description: Get a list of results for a job
      operationId: listJobResults
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
        - name: cursor
          in: query
          required: false
          schema:
            type: integer
        - name: direction
          in: query
          required: false
          schema:
            type: string
            enum: [forward, reverse]

It would be nice if in this case, "cursor" and "direction" were available as flags to be passed to the api. I know I can pass them with the -q flag, but there isn't any documentation about the query string params when printing usage docs with -h.

Comparison with curl and httpie

It would be helpful for prospective adopters to see a direct comparison of features (or main stand-out differences) between restish and alternative tools like curl and httpie.

For example, a comparison table like the ones shown by delta or zola, or even a hello world comparison like what's done in the Chain.jl README, would be very helpful to encourage people to explore this tool further.

getkin/kin-openapi breaking change causing go get failures for restish

To reproduce, you can run docker build . in a directory with the following Dockerfile:

FROM golang:1.14

ENV GO111MODULE=on
RUN go get -u github.com/danielgtaylor/restish

which results in an error at the end:

#5 36.13 # github.com/danielgtaylor/restish/openapi
#5 36.13 pkg/mod/github.com/danielgtaylor/[email protected]/openapi/openapi.go:367:16: invalid type assertion: v.Default.(string) (non-interface type string on left)
#5 36.13 pkg/mod/github.com/danielgtaylor/[email protected]/openapi/openapi.go:373:22: invalid type assertion: v.Enum[j].(string) (non-interface type string on left)
#5 36.13 pkg/mod/github.com/danielgtaylor/[email protected]/openapi/openapi.go:400:12: undefined: openapi3.NewSwaggerLoader
#5 36.13 pkg/mod/github.com/danielgtaylor/[email protected]/openapi/openapi.go:520:44: undefined: openapi3.Swagger
------
executor failed running [/bin/sh -c go get -u github.com/danielgtaylor/restish]: exit code: 2

Those errors look directly related to the breaking changes here: https://github.com/getkin/kin-openapi/#v0610

Parameter values sent when neither specified or required

Given an operation with with name $op and two path parameters $arg1 and $arg2 and two optional query parameters n and start I am making something like the following call:

โฏ restish $name -v $op $arg1 $arg2
DEBUG: Configuration: map[app-name:restish config-directory:/home/ben/.restish rsh-filter: rsh-header:[] rsh-no-cache:false rsh-no-paginate:false rsh-output-format:auto rsh-profile:default rsh-query:[] rsh-raw:false rsh-server: rsh-verbose:false server-index:0]
DEBUG: Checking API entrypoint http://localhost:8888/
DEBUG: Loading token from cache.
DEBUG: Checking http://localhost:8888/openapi.json
DEBUG: Loading token from cache.
DEBUG: Making request:
GET /some/path/$arg1/foo/$arg2?n=0&start=0 HTTP/1.1

...

Neither n nor start are required by the api nor supplied to the cli, and yet they are being filled in and sent. It's not the end of the world, but it is mildly inconvenient as it means I can't test my own parameter defaulting.

Profiles break when `openapi.servers` is defined

Spent some time trying to figure out why API generated from a flattened openapi spec wouldn't work.

Cmd such as restish hiro get-status returns ERROR: Caught error: Get "https://extended/v1/status": dial tcp: lookup extended on 8.8.8.8:53: no such host

On deletion of

servers:
  - url: https://stacks-node-api.mainnet.stacks.co/
    description: Mainnet
  - url: https://stacks-node-api.testnet.stacks.co/
    description: Testnet
  - url: http://localhost:3999/
    description: Local

The command works

Restish spec
{
  "hiro": {
    "base": "https://stacks-node-api.mainnet.stacks.co/",
    "spec_files": ["openapi.yaml"]
  }
}

running cloned code

What are the commands to build and install the code cloned from Github? (I've just been debuging through vs code but this has its limits)

How can I switch back and forth between the code I built and what is brew installed? When I'm developing a restish feature, I want want the restish command to refer to my local development instance.

What is the current release schedule? When do you plan to publish again?

Also, ss it possible to 'stable' releases, and 'nightly' releases?

~/.restish/apis.json - if you have multiple configs using the same base it round robins cached auth tokens

I am aware that I didn't have this file configured correctly - but the behavior was confusing.

I had (accidentally) copy pasted a config w/ different auth, but against the same base (rather than using profiles, which is intended) and after authenticating each profile, my results using restish would be either round robin or random with regard to which token it would use. This was very confusing!

Issues inside docker

I'm having trouble with using restish inside a docker container.

My dockerfile creates a user 'cli-user', unzips the restish code into /user/local/bin and adds an apis.json and api spc in the /home/cli-user/.restish folder

when I run my container as the cli-user, and run restish list I see this error:
**_panic: open /home/cli-user/.restish/cache.json: permission denied

goroutine 1 [running]:
github.com/danielgtaylor/restish/cli.initCache(0xd3f496, 0x7)
/home/runner/work/restish/restish/cli/cli.go:393 +0x483
github.com/danielgtaylor/restish/cli.Init(0xd3f496, 0x7, 0xf28444, 0x5)
/home/runner/work/restish/restish/cli/cli.go:101 +0x73
main.main()
/home/runner/work/restish/restish/main.go:14 +0x52_**

when I run my container as an admin and run restish list I get this error:
Caught error: Get "https://list": dial tcp: lookup list on 192.168.65.1:53: no such host

Please let me know what I can do to fix these issues. What permissions is 'cli-user missing'?

What is trying to be done on 192.168.65.1:53 ?? Do I need to make changes to my docker network

Ignore error with "$ref" to markdown

Currently if an object (tag or other) has link in description (usually used for docs generation in e.g. redoc-cli) - this will lead to error in restish.

I think it would be better to ignore them (or try to download and show)

Example:

"name": "Tag_1",
      "description":{
        "$ref":"markdown/usecases.md"
      }

setting Authorization header to avoid authentication redirect

I thought I could provide the bearer token myself using the -H flag to avoid getting prompted to authenticate but it doesn't seem to work

If there is nothing in the cache file, when I run my command, I am still prompted to login
ex

restish local users-list 1 -H "Authorization: bearer eyJhbGciOiJSUzI1NiIsInR..."

am I doing something wrong? I have a token. How can I use it to avoid being prompted to authenticate

Integer format parameters being formatted as scientific numbers

For instance:

โฏ restish $name -v $op --start 1601847165
DEBUG: Configuration: map[app-name:restish config-directory:/home/ben/.restish rsh-filter: rsh-header:[] rsh-no-cache:false rsh-no-paginate:false rsh-output-format:auto rsh-profile:default rsh-query:[] rsh-raw:false rsh-server: rsh-verbose:false server-index:0]
DEBUG: Checking API entrypoint http://localhost:8888/
DEBUG: Loading token from cache.
DEBUG: Checking http://localhost:8888/openapi.json
DEBUG: Loading token from cache.
DEBUG: Making request:
GET /beep?start=1.601847165e%2B09 HTTP/1.1

The format of the parameter however is "int64".

undefined openapi3.newSwaggerLoader/Swagger

something broken with github.com/getkin/kin-openapi?

i get this error if i try to install it via go get

go get -u github.com/danielgtaylor/restish
go: downloading github.com/danielgtaylor/restish v0.7.0
go: downloading github.com/gosimple/slug v1.9.0
go: downloading github.com/danielgtaylor/casing v0.0.0-20210126043903-4e55e6373ac3
go: downloading github.com/getkin/kin-openapi v0.33.0
go: downloading golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5
go: downloading github.com/AlecAivazis/survey/v2 v2.2.7
go: downloading github.com/alecthomas/chroma v0.8.2
go: downloading golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c
go: downloading github.com/getkin/kin-openapi v0.61.0
go: downloading github.com/amzn/ion-go v1.1.0
go: downloading github.com/andybalholm/brotli v1.0.1
go: downloading github.com/eliukblau/pixterm v1.3.1
go: downloading github.com/AlecAivazis/survey v1.8.8
go: downloading github.com/AlecAivazis/survey/v2 v2.2.12
go: downloading github.com/fxamacker/cbor/v2 v2.2.0
go: downloading github.com/gbl08ma/httpcache v1.0.2
go: downloading github.com/iancoleman/strcase v0.1.2
go: downloading github.com/andybalholm/brotli v1.0.2
go: downloading github.com/fxamacker/cbor v1.5.1
go: downloading github.com/logrusorgru/aurora v2.0.3+incompatible
go: downloading github.com/mitchellh/mapstructure v1.4.0
go: downloading github.com/iancoleman/strcase v0.1.3
go: downloading github.com/shamaton/msgpack v1.1.1
go: downloading github.com/tent/http-link-go v0.0.0-20130702225549-ac974c61c2f9
go: downloading github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be
go: downloading github.com/go-openapi/jsonpointer v0.19.5
go: downloading golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b
go: downloading github.com/shamaton/msgpack v1.2.1
go: downloading github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
go: downloading golang.org/x/text v0.3.4
go: downloading github.com/x448/float16 v0.8.4
go: downloading golang.org/x/sys v0.0.0-20201221093633-bc327ba9c2f0
go: downloading github.com/magiconair/properties v1.8.4
go: downloading github.com/pelletier/go-toml v1.8.1
go: downloading github.com/spf13/afero v1.5.1
go: downloading golang.org/x/net v0.0.0-20201216054612-986b41b23924
go: downloading golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf
go: downloading github.com/go-openapi/swag v0.19.12
go: downloading github.com/peterbourgon/diskv v2.0.1+incompatible
go: downloading golang.org/x/term v0.0.0-20210422114643-f5beecf764ed
go: downloading github.com/go-openapi/swag v0.19.15
go: downloading github.com/disintegration/imaging v1.6.2
go: downloading github.com/lucasb-eyer/go-colorful v1.0.3
go: downloading golang.org/x/image v0.0.0-20201208152932-35266b937fa6
go: downloading github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d
go: downloading github.com/lucasb-eyer/go-colorful v1.2.0
go: downloading github.com/google/btree v1.0.0
go: downloading github.com/google/btree v1.0.1
go: downloading github.com/mailru/easyjson v0.7.7
go: downloading golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb
go: downloading github.com/golang/protobuf v1.5.2
go: downloading google.golang.org/protobuf v1.26.0
go: downloading github.com/peterbourgon/diskv v1.0.0
# github.com/danielgtaylor/restish/openapi
../../../../pkg/mod/github.com/danielgtaylor/[email protected]/openapi/openapi.go:367:16: invalid type assertion: v.Default.(string) (non-interface type string on left)
../../../../pkg/mod/github.com/danielgtaylor/[email protected]/openapi/openapi.go:373:22: invalid type assertion: v.Enum[j].(string) (non-interface type string on left)
../../../../pkg/mod/github.com/danielgtaylor/[email protected]/openapi/openapi.go:400:12: undefined: openapi3.NewSwaggerLoader
../../../../pkg/mod/github.com/danielgtaylor/[email protected]/openapi/openapi.go:520:44: undefined: openapi3.Swagger

i'm facing this issue also with https://github.com/danielgtaylor/openapi-cli-generator

# github.com/danielgtaylor/openapi-cli-generator
src/github.com/danielgtaylor/openapi-cli-generator/main.go:132:40: undefined: openapi3.Swagger
src/github.com/danielgtaylor/openapi-cli-generator/main.go:625:12: undefined: openapi3.NewSwaggerLoader
src/github.com/danielgtaylor/openapi-cli-generator/main.go:626:15: undefined: openapi3.Swagger

OAuth Authorization Code - Support client_id in request body as required by Azure AD

Testing restish client against an API using OAuth Authorization Code where the identity provider is Azure AD.
This authentication fails with the following message from Azure AD AADSTS900144: The request body must contain the following parameter: 'client_id'.

The following confguration is done for restish api configure <name>

? API auth type oauth-authorization-code
? Auth parameter client_id <client_id in Azure AD>
? Auth parameter authorize_url [? for help] https://login.windows.net/common/oauth2/authorize?resource=<resource id in Azure AD>
? Auth parameter token_url https://login.microsoftonline.com/common/oauth2/token

When executing a call, the browser is opened and Azure AD gives the error message AADSTS900144: The request body must contain the following parameter: 'client_id'.

The console output is

Open your browser to log in using the URL:
https://login.windows.net/common/oauth2/authorize?resource=<resource id>?response_type=code&code_challenge=<code_challenge>&code_challenge_method=S256&client_id=<client_id>&redirect_uri=http://localhost:8484/&scope=n

Allow relative path server URLs

We are using swagger to comply with the OpenAPI 3.0 spec and currently have outlined a single server:

servers:
  - url: /v1
    name: API Version 1

We use this configuration to enable us to set the paths on each endpoint to be version-agnostic, and the swagger interface (according to the openapi spec) will use the relative path /v1 as a prefix for each of our defined paths against the current hostname being accessed.

We are hoping to gain the same functionality out of the restish configuration. When we go to add an api to restish, we are explicitly indicating the protocol/hostname of the API we are trying to access. Even though we do have the /v1 server setup, the following code indicates that it will be ignored since it is not prefixed with an absolute ${scheme}://${host}, which results in all of our paths being requested against the root of our api server instead of the path /v1.

	// See if this server has any base path prefix we need to account for.
	// TODO: handle variables in the server path?
	basePath := ""
	prefix := location.Scheme + "://" + location.Host
	for _, s := range swagger.Servers {
		if strings.HasPrefix(s.URL, prefix) {
			base, err := url.Parse(s.URL)
			if err != nil {
				return cli.API{}, err
			}
			basePath = base.Path
		}
	}

Proposed Change:

Modify the above code to respect relative server URLs. If the serverUrl is an absolute path, continue with the HasPrefix check, if not, set the basePath to the relative route /v1.

Thanks for your help, this should be a quick fix and will help get us up and running!

OpenAPI v3.1 Support

Hello! As the maintainer of openapi.tools, and as somebody works with Linux Foundation helping out in OpenAPI-land, I'm reaching out to tooling vendors to track the progress towards supporting OpenAPI v3.1, to see what roadblocks there are beyond folks just generally being busy at this ridiculous time.

I saw this, and I am going to guess it means 3.0 only:

In general, OpenAPI 3 just works with Restish. There are a couple of things you can do to make sure your users can more easily use Restish with your API.

OpenAPI v3.1 has a bunch of great little changes, solving problems like the the JSON Schema <!=> OpenAPI Schema Object divergence. It also fixes some other inconsistencies and duplicate ways of doing things. It's the best version and everyone should be using it, but we need tooling to catch up. Just in case folks didn't notice, or don't have resources to simplify the process, I'm here to give a friendly prod and send over some handy links.

Here are a few articles showing off the differences between OpenAPI v3.0 and v3.1.

Here are some example files which can make for handy pass/fail test cases:

https://github.com/Mermade/openapi3-examples/tree/master/3.1

If you're looking for the JSON Schema that defines a valid OpenAPI document, that'll be right over here:

https://github.com/OAI/OpenAPI-Specification/tree/main/schemas/v3.1

No rush, but when you're starting work on it, please update this issue so I can update openapi.tools to reflect that, and folks will have a way to subscribe for updates.

LMK if you have any questions!

Error unmarshaling JSON

Below is a schema that causes an unmarshalling error

panic: error unmarshaling JSON: failed to unmarshal property "paths" (*openapi3.Paths): failed to unmarshal property "post" (*openapi3.Operation): failed to unmarshal property "responses" (*openapi3.Responses): failed to unmarshal property "content" (*openapi3.Content): failed to unmarshal property "schema" (*openapi3.SchemaRef): failed to unmarshal property "properties" (*openapi3.Schemas): failed to unmarshal property "properties" (*openapi3.Schemas): failed to unmarshal property "type" (*string): json: cannot unmarshal array into Go value of type string

goroutine 1 [running]:
github.com/danielgtaylor/restish/cli.Run()
	/home/runner/work/restish/restish/cli/cli.go:493 +0xb12
main.main()
	/home/runner/work/restish/restish/main.go:27 +0x177
OpenAPI schema issue
openapi: 3.0.2
info:
  title: Stacks 2.0 Blockchain API
  version: STACKS_API_VERSION
  contact:
    name: API developers
    url: 'https://github.com/blockstack/stacks-blockchain-api/issues'
    email: [email protected]
  description: >
    This is the documentation for the Stacks 2.0 Blockchain API. It is comprised
    of two parts; the Stacks Blockchain API and the Stacks Core API. <a
    href="collection.json" download="collection.json">Download Postman
    collection</a>
paths:
  /rosetta/v1/construction/preprocess:
    post:
      tags:
        - Rosetta
      summary: Create a Request to Fetch Metadata
      operationId: rosetta_construction_preprocess
      description: TODO
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $schema: 'http://json-schema.org/draft-07/schema'
                $id: rosetta-construction-preprocess-response
                type: object
                title: RosettaConstructionPreprocessResponse
                description: >-
                  RosettaConstructionPreprocessResponse contains options that
                  will be sent unmodified to /construction/metadata. If it is
                  not necessary to make a request to /construction/metadata,
                  options should be omitted. Some blockchains require the
                  PublicKey of particular AccountIdentifiers to construct a
                  valid transaction. To fetch these PublicKeys, populate
                  required_public_keys with the AccountIdentifiers associated
                  with the desired PublicKeys. If it is not necessary to
                  retrieve any PublicKeys for construction, required_public_keys
                  should be omitted.
                required: []
                properties:
                  options:
                    $id: rosetta-construction-options
                    title: RosettaOptions
                    type: object
                    description: >-
                      The options that will be sent directly to
                      /construction/metadata by the caller.
                    required: []
                    properties:
                      sender_address:
                        type: string
                        description: 'sender''s address '
                      type:
                        type: string
                        description: Type of operation e.g transfer
                      status:
                        type:
                          - string
                          - 'null'
                        description: This value indicates the state of the operations
                      token_transfer_recipient_address:
                        type: string
                        description: Recipient's address
                      amount:
                        type: string
                        description: Amount to be transfered.
                      symbol:
                        type: string
                        description: Currency symbol e.g STX
                      decimals:
                        type: integer
                        description: Number of decimal places
                      gas_limit:
                        type: number
                        description: Maximum price a user is willing to pay.
                      gas_price:
                        type: number
                        description: Cost necessary to perform a transaction on the network
                      suggested_fee_multiplier:
                        type: number
                        description: ' A suggested fee multiplier to indicate that the suggested fee should be scaled. This may be used to set higher fees for urgent transactions or to pay lower fees when there is less urgency.'
                      max_fee:
                        type: string
                        description: Maximum fee user is willing to pay
                      fee:
                        type: string
                        description: Fee for this transaction
                      size:
                        type: integer
                        description: >-
                          Transaction approximative size (used to calculate
                          total fee).
                      memo:
                        type: string
                        description: STX token transfer memo.
                      number_of_cycles:
                        type: integer
                        description: Number of cycles when stacking.
                      contract_address:
                        type: string
                        description: Address of the contract to call.
                      contract_name:
                        type: string
                        description: Name of the contract to call.
                      burn_block_height:
                        type: integer
                        description: >-
                          Set the burnchain (BTC) block for stacking lock to
                          start.
                      delegate_to:
                        type: string
                        description: >-
                          Delegator address for when calling
                          `delegate-stacking`.
                      pox_addr:
                        type: string
                        description: >-
                          The reward address for stacking transaction. It should
                          be a valid Bitcoin address
                  required_public_keys:
                    type: array
                    items:
                      type: object
                      title: RosettaAccount
                      description: >-
                        The account_identifier uniquely identifies an account
                        within a network. All fields in the account_identifier
                        are utilized to determine this uniqueness (including the
                        metadata field, if populated).
                      required:
                        - address
                      properties:
                        address:
                          type: string
                          description: >-
                            The address may be a cryptographic public key (or
                            some encoding of it) or a provided username.
                        sub_account:
                          type: object
                          title: RosettaSubAccount
                          description: >-
                            An account may have state specific to a contract
                            address (ERC-20 token) and/or a stake (delegated
                            balance). The sub_account_identifier should specify
                            which state (if applicable) an account instantiation
                            refers to.
                          required:
                            - address
                          properties:
                            address:
                              type: string
                              description: >-
                                The address may be a cryptographic public key
                                (or some encoding of it) or a provided username.
                            metadata:
                              type: object
                              description: >-
                                If the SubAccount address is not sufficient to
                                uniquely specify a SubAccount, any other
                                identifying information can be stored here. It
                                is important to note that two SubAccounts with
                                identical addresses but differing metadata will
                                not be considered equal by clients.
                              required: []
                        metadata:
                          type: object
                          description: >-
                            Blockchains that utilize a username model (where the
                            address is not a derivative of a cryptographic
                            public key) should specify the public key(s) owned
                            by the address in metadata.
                          required: []
        '400':
          description: Error
          content:
            application/json:
              schema:
                $schema: 'http://json-schema.org/draft-07/schema'
                $id: Rosetta-errors
                type: object
                title: RosettaError
                description: >-
                  Instead of utilizing HTTP status codes to describe node errors
                  (which often do not have a good analog), rich errors are
                  returned using this object. Both the code and message fields
                  can be individually used to correctly identify an error.
                  Implementations MUST use unique values for both fields.
                required:
                  - code
                  - message
                  - retriable
                properties:
                  code:
                    type: integer
                    description: >-
                      Code is a network-specific error code. If desired, this
                      code can be equivalent to an HTTP status code.
                  message:
                    type: string
                    description: >-
                      Message is a network-specific error message. The message
                      MUST NOT change for a given code. In particular, this
                      means that any contextual information should be included
                      in the details field.
                  retriable:
                    type: boolean
                    description: >-
                      An error is retriable if the same request may succeed if
                      submitted again.
                  details:
                    type: object
                    description: >-
                      Often times it is useful to return context specific to the
                      request that caused the error (i.e. a sample of the stack
                      trace or impacted account) in addition to the standard
                      error message.
                    required: []
                    properties:
                      address:
                        type: string
                      error:
                        type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $schema: 'http://json-schema.org/draft-07/schema'
              $id: rosett-construction-preprocess-schema
              type: object
              title: RosettaConstructionPreprocessRequest
              description: >-
                ConstructionPreprocessRequest is passed to the
                /construction/preprocess endpoint so that a Rosetta
                implementation can determine which metadata it needs to request
                for construction
              required:
                - network_identifier
                - operations
              properties:
                network_identifier:
                  $schema: 'http://json-schema.org/draft-07/schema'
                  type: object
                  title: NetworkIdentifier
                  description: >-
                    The network_identifier specifies which network a particular
                    object is associated with.
                  required:
                    - blockchain
                    - network
                  properties:
                    blockchain:
                      type: string
                      description: Blockchain name
                    network:
                      type: string
                      description: >-
                        If a blockchain has a specific chain-id or network
                        identifier, it should go in this field. It is up to the
                        client to determine which network-specific identifier is
                        mainnet or testnet.
                    sub_network_identifier:
                      type: object
                      description: >-
                        In blockchains with sharded state, the
                        SubNetworkIdentifier is required to query some object on
                        a specific shard. This identifier is optional for all
                        non-sharded blockchains.
                      required:
                        - network
                      properties:
                        network:
                          type: string
                          description: Network name
                        metadata:
                          type: object
                          description: Meta data from subnetwork identifier
                          required:
                            - producer
                          properties:
                            producer:
                              type: string
                              description: producer
                operations:
                  type: array
                  items:
                    type: object
                    title: RosettaOperation
                    description: >-
                      Operations contain all balance-changing information within
                      a transaction. They are always one-sided (only affect 1
                      AccountIdentifier) and can succeed or fail independently
                      from a Transaction.
                    required:
                      - operation_identifier
                      - type
                    properties:
                      operation_identifier:
                        description: >-
                          The operation_identifier uniquely identifies an
                          operation within a transaction.
                        type: object
                        title: RosettaOperationIdentifier
                        required:
                          - index
                        properties:
                          index:
                            type: integer
                            description: >-
                              The operation index is used to ensure each
                              operation has a unique identifier within a
                              transaction. This index is only relative to the
                              transaction and NOT GLOBAL. The operations in each
                              transaction should start from index 0. To clarify,
                              there may not be any notion of an operation index
                              in the blockchain being described.
                          network_index:
                            type: integer
                            description: >-
                              Some blockchains specify an operation index that
                              is essential for client use. For example, Bitcoin
                              uses a network_index to identify which UTXO was
                              used in a transaction. network_index should not be
                              populated if there is no notion of an operation
                              index in a blockchain (typically most
                              account-based blockchains).
                      related_operations:
                        type: array
                        description: >-
                          Restrict referenced related_operations to identifier
                          indexes < the current operation_identifier.index. This
                          ensures there exists a clear DAG-structure of
                          relations. Since operations are one-sided, one could
                          imagine relating operations in a single transfer or
                          linking operations in a call tree.
                        items:
                          title: RosettaRelatedOperation
                          type: object
                          description: >-
                            Restrict referenced related_operations to identifier
                            indexes < the current operation_identifier.index.
                            This ensures there exists a clear DAG-structure of
                            relations. Since operations are one-sided, one could
                            imagine relating operations in a single transfer or
                            linking operations in a call tree.
                          required:
                            - index
                          properties:
                            index:
                              type: integer
                              description: Describes the index of related operation.
                            network_index:
                              type: integer
                              description: >-
                                Some blockchains specify an operation index that
                                is essential for client use. network_index
                                should not be populated if there is no notion of
                                an operation index in a blockchain (typically
                                most account-based blockchains).
                      type:
                        type: string
                        description: >-
                          The network-specific type of the operation. Ensure
                          that any type that can be returned here is also
                          specified in the NetworkStatus. This can be very
                          useful to downstream consumers that parse all block
                          data.
                      status:
                        type: string
                        description: >-
                          The network-specific status of the operation. Status
                          is not defined on the transaction object because
                          blockchains with smart contracts may have transactions
                          that partially apply. Blockchains with atomic
                          transactions (all operations succeed or all operations
                          fail) will have the same status for each operation.
                      account:
                        type: object
                        title: RosettaAccount
                        description: >-
                          The account_identifier uniquely identifies an account
                          within a network. All fields in the account_identifier
                          are utilized to determine this uniqueness (including
                          the metadata field, if populated).
                        required:
                          - address
                        properties:
                          address:
                            type: string
                            description: >-
                              The address may be a cryptographic public key (or
                              some encoding of it) or a provided username.
                          sub_account:
                            type: object
                            title: RosettaSubAccount
                            description: >-
                              An account may have state specific to a contract
                              address (ERC-20 token) and/or a stake (delegated
                              balance). The sub_account_identifier should
                              specify which state (if applicable) an account
                              instantiation refers to.
                            required:
                              - address
                            properties:
                              address:
                                type: string
                                description: >-
                                  The address may be a cryptographic public key
                                  (or some encoding of it) or a provided
                                  username.
                              metadata:
                                type: object
                                description: >-
                                  If the SubAccount address is not sufficient to
                                  uniquely specify a SubAccount, any other
                                  identifying information can be stored here. It
                                  is important to note that two SubAccounts with
                                  identical addresses but differing metadata
                                  will not be considered equal by clients.
                                required: []
                          metadata:
                            type: object
                            description: >-
                              Blockchains that utilize a username model (where
                              the address is not a derivative of a cryptographic
                              public key) should specify the public key(s) owned
                              by the address in metadata.
                            required: []
                      amount:
                        type: object
                        title: RosettaAmount
                        description: >-
                          Amount is some Value of a Currency. It is considered
                          invalid to specify a Value without a Currency.
                        required:
                          - value
                          - currency
                        properties:
                          value:
                            type: string
                            description: >-
                              Value of the transaction in atomic units
                              represented as an arbitrary-sized signed integer.
                              For example, 1 BTC would be represented by a value
                              of 100000000.
                          currency:
                            description: >-
                              Currency is composed of a canonical Symbol and
                              Decimals. This Decimals value is used to convert
                              an Amount.Value from atomic units (Satoshis) to
                              standard units (Bitcoins).
                            title: RosettaCurrency
                            type: object
                            required:
                              - symbol
                              - decimals
                            properties:
                              symbol:
                                type: string
                                description: Canonical symbol associated with a currency.
                              decimals:
                                type: integer
                                description: >-
                                  Number of decimal places in the standard unit
                                  representation of the amount. For example, BTC
                                  has 8 decimals. Note that it is not possible
                                  to represent the value of some currency in
                                  atomic units that is not base 10.
                              metadata:
                                type: object
                                description: >-
                                  Any additional information related to the
                                  currency itself. For example, it would be
                                  useful to populate this object with the
                                  contract address of an ERC-20 token.
                          metadata:
                            type: object
                            description: ''
                            required: []
                      coin_change:
                        type: object
                        title: RosettaCoinChange
                        description: >-
                          CoinChange is used to represent a change in state of a
                          some coin identified by a coin_identifier. This object
                          is part of the Operation model and must be populated
                          for UTXO-based blockchains. Coincidentally, this
                          abstraction of UTXOs allows for supporting both
                          account-based transfers and UTXO-based transfers on
                          the same blockchain (when a transfer is account-based,
                          don't populate this model).
                        required:
                          - coin_identifier
                          - coin_action
                        properties:
                          coin_identifier:
                            type: object
                            description: CoinIdentifier uniquely identifies a Coin.
                            required:
                              - identifier
                            properties:
                              identifier:
                                type: string
                                description: >-
                                  Identifier should be populated with a globally
                                  unique identifier of a Coin. In Bitcoin, this
                                  identifier would be transaction_hash:index.
                          coin_action:
                            type: string
                            description: >-
                              CoinActions are different state changes that a
                              Coin can undergo. When a Coin is created, it is
                              coin_created. When a Coin is spent, it is
                              coin_spent. It is assumed that a single Coin
                              cannot be created or spent more than once.
                            enum:
                              - coin_created
                              - coin_spent
                      metadata:
                        type: object
                        description: Operations Meta Data
                metadata:
                  type: object
                max_fee:
                  type: array
                  items:
                    $id: rosetta-max-fee
                    type: object
                    title: RosettaMaxFeeAmount
                    description: >-
                      Amount is some Value of a Currency. It is considered
                      invalid to specify a Value without a Currency.
                    required:
                      - value
                      - currency
                    properties:
                      value:
                        type: string
                        description: >-
                          Value of the transaction in atomic units represented
                          as an arbitrary-sized signed integer. For example, 1
                          BTC would be represented by a value of 100000000.
                      currency:
                        description: >-
                          Currency is composed of a canonical Symbol and
                          Decimals. This Decimals value is used to convert an
                          Amount.Value from atomic units (Satoshis) to standard
                          units (Bitcoins).
                        title: RosettaCurrency
                        type: object
                        required:
                          - symbol
                          - decimals
                        properties:
                          symbol:
                            type: string
                            description: Canonical symbol associated with a currency.
                          decimals:
                            type: integer
                            description: >-
                              Number of decimal places in the standard unit
                              representation of the amount. For example, BTC has
                              8 decimals. Note that it is not possible to
                              represent the value of some currency in atomic
                              units that is not base 10.
                          metadata:
                            type: object
                            description: >-
                              Any additional information related to the currency
                              itself. For example, it would be useful to
                              populate this object with the contract address of
                              an ERC-20 token.
                      metadata:
                        type: object
                        description: ''
                        required: []
                suggested_fee_multiplier:
                  type: integer
                  description: ' The caller can also provide a suggested fee multiplier to indicate that the suggested fee should be scaled. This may be used to set higher fees for urgent transactions or to pay lower fees when there is less urgency. It is assumed that providing a very low multiplier (like 0.0001) will never lead to a transaction being created with a fee less than the minimum network fee (if applicable). In the case that the caller provides both a max fee and a suggested fee multiplier, the max fee will set an upper bound on the suggested fee (regardless of the multiplier provided).'

Oauth <-> output-format=json: invalid Json

When Oauth is used, restish --rsh-output-format=json outputs non-JSON to stdout, which confuses existing JSON pipeline:

Open your browser to log in using the URL: ...
Alternatively, enter the code manually: 

(if pipelined to | jq, one gets parse error: Invalid numeric literal at line 1, column 5 and Oauth credentials fail to get cached)

Maybe the Oauth output could be done on stderr ?

got error while file is correct in swagger and redocly

goroutine 1 [running]:
github.com/danielgtaylor/restish/cli.Run()
/home/runner/work/restish/restish/cli/cli.go:496 +0x94c
main.main()
/home/runner/work/restish/restish/main.go:27 +0x238

How I can verify openapi file with restish and get more information?

No authorization header sent for oauth-authorization-code

I'm using restish 0.4.3 with oauth-authorization-code. It's an auth0 api, it's basically copy-pasta from the example in the docs. The client seems to do all the right things in as much as it opens a browser window, and then tells me it's logged in successfully and I can close the window. The problem I am having is that restish never seems to send any kind of authorization header, which I have verified with wireshark. I have tried running it with verbose logging but that doesn't seem to log anything actionable. I'd appreciate any tips you could offer on debugging the issue

Recursive decent inserting nils

Given an endpoint that returns a repetitive structure with no nil value results such as:

[
  {
    fqdn: ""
    id: "f44ef09a-102f-4a98-952e-04b64fe2b2bd"
    state: ""
  }
  {
    fqdn: "node2"
    id: "1af9adc3-acad-47f8-8120-8fee87d809ae"
    state: ""
  }
  {
    fqdn: "node3"
    id: "710a97dd-dbe5-41c5-acd2-db842da655eb"
    state: ""
  }
]

trying to use the recursive decent feature:

get-nodes -f ..{id}

results in output that has extraneous nulls inserted:

[
  {
    "id": null
  },
  {
    "id": null
  },
  {
    "id": "f44ef09a-102f-4a98-952e-04b64fe2b2bd"
  },
  {
    "id": "1af9adc3-acad-47f8-8120-8fee87d809ae"
  },
  {
    "id": "710a97dd-dbe5-41c5-acd2-db842da655eb"
  },
  {
    "id": null
  }
]

However if I do not use recursive decent it does not insert those nil results in.

get-nodes -f "body[].{id}"

result:

[
  {
    "id": "f44ef09a-102f-4a98-952e-04b64fe2b2bd"
  },
  {
    "id": "1af9adc3-acad-47f8-8120-8fee87d809ae"
  },
  {
    "id": "710a97dd-dbe5-41c5-acd2-db842da655eb"
  }
]

How to use a Self Signed CA Cert with an API

Is there a way to use a Self Signed CA Cert (Corporate CA) with a specific API without having to add it to the System CA Cert location? We do not necessarily have root access on our deployment agents in which to load the CA Cert ..

Post csv file not working

I have Restful service with post to upload csv file.
When run: restish post http://localhost:8180/upload <georg_batch.csv, I got error:

HTTP/1.1 400 Bad Request
Connection: keep-alive
Content-Length: 240
Content-Type: text/html;charset=UTF-8
Date: Fri, 28 May 2021 06:19:23 GMT

com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'Id': was expecting 'null', 'true', 'false' or NaN
at [Source: (io.undertow.servlet.spec.ServletInputStreamImpl); line: 1, column: 4]
(base)

specifying api base url

I would like to be able to specify the base url at the command line and remove the 'base' property from the .restish/api.json

I have tried using the -s flag but this did not seem to work.
Setting the env variable RSH_SERVER to my base url also did not work

I would also like to specify the value from the spec_files array field at the command line as opposed to getting it from the api.json file. Is this possible or can we make this a feature?

Thanks

make operations more readable

Operation names in OpenAPI specs are commonly camelcase. Currently (as shown in https://github.com/danielgtaylor/restish/blob/main/openapi/openapi_test.go) an operation like createPets turns into createpets in the CLI. It seems like it'd be generally better if this turned into create-pets instead. In the actual API I'm starting to use Restish for, there are operations like getsourcedefinitionspecification which would be significantly more readable as get-source-definition-specification.

While it's possible to add x-cli-name for each operation, this is really annoying for an API with a lot of endpoints.

Can we instead add ToKebab from https://github.com/iancoleman/strcase before slug.Make by default? If you're concerned about backwards compatibility, we might need a project-specific config option for ~/.restish/apis.json.

If this sounds good I'd be happy to submit a PR.

How to create profile without API authentication

Hi,

I'm using restish to interact with an API that supports authenticating via API keys. I have configured a profile that sets the appropriate header, but restish insists on inserting an "empty" "auth" section in the profile configuration:

        "auth": { 
          "name": "oauth-authorization-code", 
          "params": { 
            "authorize_url": "oauth2/authorize", 
            "client_id": "", 
            "token_url": "oauth2/token" 
          }

If I remove this from the configuration everything works. Is there a way to create a profile without configuring authentication information?

Add flag for IsExternalRefsAllowed in kin-openapi to support multifile openapi specs

Thank you for this project!
Having your open API spec spread to several external files, using refs, seems not to work.
It gives you external refs not allowed error, which originates from kin-openapi. I tried setting the loader.isExternalRefsAllowed = true, on the loader := openapi3.NewLoader(), in openapi/openapi.go (line 401) and then recompile. This does solve the issue.

However, I imagine it is better to expose the flag to the user instead of leaving it on all the time. I tried to see if it is possible to get such a flag from the root cobra cmd, but I am not too familiar with cobra and viper.

`style: form` in parameter leads to error

Having this minimal openapi spec:

openapi: 3.0.0
servers:
- url: /
paths:
  /foo:
    get:
      operationId: foo
      parameters:
      - description: bar
        explode: false
        in: query
        name: ids
        required: false
        schema:
          items:
            type: string
          type: array
        style: form

      responses:
        "200":
          content:
            application/json:
              schema:
                type: string
          description: OK
      summary: Foo
      tags:
      - foo

and running

restish test foo

yields

ERROR: Caught error: interface conversion: interface {} is []string, not []interface {}

It seems to be related to style: form. One can work around the issue by removing style: form. But since this setting is valid to the spec, restish should be able to handle it.

Authorization Code flow wrong cache key

The authorization code workflow caches the authorization url as authorization_url; however, its usage in the remainder of the flow is for the name AuthorizeUrl (authorize_url). This results in an invalid authorization code URL being presented to the console.

Cached usage: https://github.com/danielgtaylor/restish/blob/master/oauth/authcode.go#L157

func (h *AuthorizationCodeHandler) Parameters() []cli.AuthParam {
	return []cli.AuthParam{
		{Name: "client_id", Required: true, Help: "OAuth 2.0 Client ID"},
		{Name: "authorization_url", Required: true, Help: "OAuth 2.0 authorization URL, e.g. https://api.example.com/oauth/authorize"},
		{Name: "token_url", Required: true, Help: "OAuth 2.0 token URL, e.g. https://api.example.com/oauth/token"},
		{Name: "scopes", Help: "Optional scopes to request in the token"},
	}
}

Proposed Change:

func (h *AuthorizationCodeHandler) Parameters() []cli.AuthParam {
	return []cli.AuthParam{
		{Name: "client_id", Required: true, Help: "OAuth 2.0 Client ID"},
		{Name: "authorize_url", Required: true, Help: "OAuth 2.0 authorization URL, e.g. https://api.example.com/oauth/authorize"},
		{Name: "token_url", Required: true, Help: "OAuth 2.0 token URL, e.g. https://api.example.com/oauth/token"},
		{Name: "scopes", Help: "Optional scopes to request in the token"},
	}
}

Empty Available commands

I am working with a local api server, on plain http. I have configured an api profile and added some command aliases. These aren't listed by running

restish $name --help

but if I run

restish $name $alias

They are are recognised, so it just seems like it's the display rather than the discovery that's busted. I'd love to offer a PR but go isn't in my repertoire.

Released to AUR

Not really an issue, more an FYI. I have an AUR build up and running. If you ever want to take over, or be added as a maintainer or whatever let me know. Otherwise I'll just keep it chugging along.

questions around the spec document

I have a few questions related to the openApi spec document

  1. can the spec_files array contain urls?

  2. There may be a bug related to path resolution in the spec array. I copied the openapi.json file to my ~/.restish folder but I discovered that I can not specify the path relative to ~ ex "spec_files": [ "~/.restish/ls-openapi.json"]
    leads to an error goroutine 1 [running]: github.com/danielgtaylor/restish/cli.Run() /home/runner/work/restish/restish/cli/cli.go:486 +0x9f2 main.main() /home/runner/work/restish/restish/main.go:27 +0x177
    but "spec_files": [ "./ls-openapi.json"] works.

  3. If I want to combine the hosted openapi.json file with a local-api.json file that has some customizations, will that be possible?

API management

It would be handy to have additional API management functionality. Currently, only the api configure subcommand is available. Useful additions would be:

  • api delete
  • api show

spec file path resolution

because I am using a spec file in my apis.json file, this was forcing me to run restish from my ~/.restish directory to avoid a path resolution retlated error
to avoid this, I added this to my .zshrc file:

restish_call () {
          pushd ~/.restish; restish $@; popd
}

alias restish="restish_call"

now I can call restish from anywhere. Was there some other alternative though to fix the path resolution?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.