Giter VIP home page Giter VIP logo

resty's Introduction

Resty

GitHub release Build Status GitHub license

Resty is a tiny script wrapper for curl.

It provides a simple, concise shell interface for interacting with REST services. Since it is implemented as functions in your shell and not in its own separate command environment you have access to all the powerful shell tools, such as perl, awk, grep, sed, etc. You can use resty in pipelines to process data from REST services, and PUT, PATCH, or POST the data right back. You can even pipe the data in and then edit it interactively in your text editor prior to PUT, PATCH, or POST.

Cookies are supported automatically and stored in a file locally. Most of the arguments are remembered from one call to the next to save typing. It has pretty good defaults for most purposes. Additionally, resty allows you to easily provide your own options to be passed directly to curl, so even the most complex requests can be accomplished with the minimum amount of command line pain.

Here is a nice screencast showing resty in action (by Jan-Piet Mens).

Quick Start

You have curl, right? Okay.

  $ curl -L https://raw.githubusercontent.com/micha/resty/master/resty > resty

Source the script before using it.

  $ . resty

Once resty is installed, set your REST host to which you will be making your requests.

  $ resty http://127.0.0.1:8080/data
  http://127.0.0.1:8080/data*

And now you can Make some HTTP requests.

  $ GET /blogs.json
  [ {"id" : 1, "title" : "first post", "body" : "This is the first post"}, ... ]

  $ PUT /blogs/2.json '{"id" : 2, "title" : "updated post", "body" : "This is the new."}'
  {"id" : 2, "title" : "updated post", "body" : "This is the new."}

  $ DELETE /blogs/2

  $ POST /blogs.json '{"title" : "new post", "body" : "This is the new new."}'
  {"id" : 204, "title" : "new post", "body" : "This is the new new."}

Installation

There are several way to install resty other than curling it and sourcing it.

Here are some shell package manager that are supported:

  • Bpkg : with bpkg installed just run bpkg install -g micha/resty, then follow the instruction by adding source ~/.bashrc.d/resty to your bashrc
  • Antigen : with antigen for zsh, just add antigen bundle micha/resty in your .zshrc
  • Zplug: with zplug installed, just add zplug micha/resty, use:'resty' in your .zshrc
  • Oh my Zsh: clone the github repositery in the plugins directory of ZSH_CUSTOM and add resty to you plugins list

Usage

  source resty [-W] [remote] [OPTIONS]    # load functions into shell
  resty [-v]                              # prints current request URI base
  resty <remote> [OPTIONS]                # sets the base request URI

  HEAD [path] [OPTIONS]                   # HEAD request
  OPTIONS [path] [OPTIONS]                # OPTIONS request
  GET [path] [OPTIONS]                    # GET request
  DELETE [path] [OPTIONS]                 # DELETE request
  PUT [path] [data] [OPTIONS]             # PUT request
  PATCH [path] [data] [OPTIONS]           # PATCH request
  POST [path] [data] [OPTIONS]            # POST request
  TRACE [path] [OPTIONS]                  # TRACE request

  Options:

  -Q            Don't URL encode the path.
  -q <query>    Send query string with the path. A '?' is prepended to
                <query> and concatenated onto the <path>.
  -W            Don't write to history file (only when sourcing script).
  -V            Edit the input data interactively in 'vi'. (PUT, PATCH,
                and POST requests only, with data piped to stdin.)
  -Z            Raw output. This disables any processing of HTML in the
                response.
  -v            Verbose output. When used with the resty command itself
                this prints the saved curl options along with the current
                URI base. Otherwise this is passed to curl for verbose
                curl output.
  --dry-run     Just output the curl command.
  <curl opt>    Any curl options will be passed down to curl.

Configuration, Data File Locations

Resty creates a few files in either your ${XDG_CONFIG_HOME} and ${XDG_DATA_HOME} directory (if your linux uses the XDG directory standard) or in the ~/.resty directory, otherwise.

Using Existing, Pre-v2.1 Configuration Files With v2.1

If you had resty installed before version 2.1 and your system uses the XDG config directory standard and you want to continue using your existing configuration files, please make a backup of your ~/.resty directory and then do:

  $ mkdir -p "${XDG_CONFIG_HOME}/resty" "${XDG_DATA_HOME}/resty"
  $ mv ~/.resty/c "${XDG_DATA_HOME}/resty"
  $ mv ~/.resty/* "${XDG_CONFIG_HOME}/resty"

Request URI Base

The request URI base is what the eventual URI to which the requests will be made is based on. Specifically, it is a URI that may contain the * character one or more times. The * will be replaced with the path parameter in the OPTIONS, HEAD, GET, POST, PUT, PATCH, or DELETE request as described above.

For example:

  $ resty 'http://127.0.0.1:8080/data*.json'
  http://127.0.0.1:8080/data*.json

and then

  $ GET /5
  { "the_response" : true }

would result in a GET request to the URI http://127.0.0.1:8080/data/5.json.

If no * character is specified when setting the base URI, it's just added onto the end for you automatically.

HTTPS URIs

HTTPS URIs can be used, as well. For example:

  $ resty 'https://example.com/doit'
  https://example.com/doit*

URI Base History

The URI base is saved to an rc file (${XDG_CONFIG_HOME}/resty/host or ~/.resty/host) each time it's set, and the last setting is saved in an environment variable ($_resty_host). The URI base is read from the rc file when resty starts up, but only if the $_resty_host environment variable is not set. In this way you can make requests to different hosts using resty from separate terminals, and have a different URI base for each terminal.

If you want to see what the current URI base is, just run resty with no arguments. The URI base will be printed to stdout.

The Optional Path Parameter

The HTTP verbs (OPTIONS, HEAD, GET, POST, PUT, PATCH, and DELETE) first argument is always an optional URI path. This path must always start with a / character. If the path parameter is not provided on the command line, resty will just use the last path it was provided with. This "last path" is stored in an environment variable ($_RESTY_PATH), so each terminal basically has its own "last path".

This feature can be disabled with the following flag RESTY_NO_PRESERVE_PATH=true.

URL Encoding Of Path Parameter

Resty will always [URL encode] (http://www.blooberry.com/indexdot/html/topics/urlencoding.htm) the path, except for slashes. (Slashes in path elements need to be manually encoded as %2F.) This means that the ?, =, and & characters will be encoded, as well as some other problematic characters. To disable this behavior use the -Q option.

Query Strings, POST Parameters, And Both At The Same Time

There are three ways to add a query string to the path. The first, mentioned above, is to disable URL encoding with the -Q option, and include the query string with the path parameter, like this:

  $ GET '/blogs/47?param=foo&otherparam=bar' -Q

To specify a query string without disabling URL encoding on the path the -q option is used, like this:

  $ GET /blogs/47 -q 'param=foo&otherparam=bar'

Finally, you can use the curl -d and -G options, like this:

  $ GET /blogs/47 -d 'param=foo' -d 'otherparam=bar' -G

However, if you want to pass both GET parameters in the query string and POST parameters in the request body, curl cannot support this by itself. Using the -q or -Q resty options with the -d curl option will accomplish this, like so:

  $ POST '/blogs/47?param=foo&otherparam=bar' -Q -d 'postparam=baz'

POST/PUT/PATCH Requests and Data

Normally you would probably want to provide the request body data right on the command line like this:

  $ PUT /blogs/5.json '{"title" : "hello", "body" : "this is it"}'

But sometimes you will want to send the request body from a file instead. To do that you pipe in the contents of the file:

  $ PUT /blogs/5.json < /tmp/t

Or you can pipe the data from another program, like this:

  $ myprog | PUT /blogs/5.json

Or, interestingly, as a filter pipeline with jsawk:

  $ GET /blogs/5.json | jsawk 'this.author="Bob Smith";this.tags.push("news")' | PUT

Notice how the path argument is omitted from the PUT command.

Edit PUT/PATCH/POST Data In Vi

With the -V options you can pipe data into PUT, PATCH, or POST, edit it in vi, save the data (using :wq in vi, as normal) and the resulting data is then PUT, PATCH, or POSTed. This is similar to the way visudo works, for example.

  $ GET /blogs/2 | PUT -V

This fetches the data and lets you edit it, and then does a PUT on the resource. If you don't like vi you can specify your preferred editor by setting the EDITOR environment variable.

Errors and Output

For successful 2xx responses, the response body is printed on stdout. You can pipe the output to stuff, process it, and then pipe it back to resty, if you want.

For responses other than 2xx the response body is dumped to stderr.

In either case, if the content type of the response is text/html, then resty will try to process the response through either lynx, html2text, or, finally, cat, depending on which of those programs are available on your system.

Raw Output (-Z option)

If you don't want resty to process the output through lynx or html2text you can use the -Z option, and get the raw output.

Passing Command Line Options To Curl

Anything after the (optional) path and data arguments is passed on to curl.

For example:

  $ GET /blogs.json -H "Range: items=1-10"

The -H "Range: items=1-10" argument will be passed to curl for you. This makes it possible to do some more complex operations when necessary.

  $ POST -v -u user:test

In this example the path and data arguments were left off, but -v and -u user:test will be passed through to curl, as you would expect.

Here are some useful options to try:

  • -v verbose output, shows HTTP headers and status on stderr
  • -j junk session cookies (refresh cookie-based session)
  • -u <username:password> HTTP basic authentication
  • -H <header> add request header (this option can be added more than once)

Setting The Default Curl Options

Sometimes you want to send some options to curl for every request. It would be tedious to have to repeat these options constantly. To tell resty to always add certain curl options you can specify those options when you call resty to set the URI base. For example:

  $ resty example.com:8080 -H "Accept: application/json" -u user:pass

Every subsequent request will have the -H "Accept:..." and -u user:... options automatically added. Each time resty is called this option list is reset.

Per-Host/Per-Method Curl Configuration Files

Resty supports a per-host/per-method configuration file to help you with frequently used curl options. Each host (including the port) can have its own configuration file in the ~/.resty directory. A special host resty is used to define default options for all the hosts.

The file format is

  GET [arg] [arg] ...
  PUT [arg] [arg] ...
  PATCH [arg] [arg] ...
  POST [arg] [arg] ...
  DELETE [arg] [arg] ...

Where the args are curl command line arguments. Each line can specify arguments for that HTTP verb only, and all lines are optional.

These config files are loaded each time you run the resty command.

Example

So, suppose you find yourself using the same curl options over and over. You can save them in a file and resty will pass them to curl for you. Say this is a frequent pattern for you:

  $ resty localhost:8080
  $ GET /Blah -H "Accept: application/json"
  $ GET /Other -H "Accept: application/json"
  ...
  $ POST /Something -H "Content-Type: text/plain" -u user:pass
  $ POST /SomethingElse -H "Content-Type: text/plain" -u user:pass
  ...

It's annoying to add the -H and -u options to curl all the time. So create a file ~/.resty/localhost:8080, like this:

~/.resty/localhost:8080

  GET -H "Accept: application/json"
  POST -H "Content-Type: text/plain" -u user:pass

Then any GET or POST requests to localhost:8080 will have the specified options prepended to the curl command line arguments, saving you from having to type them out each time, like this:

  $ GET /Blah
  $ GET /Other
  ...
  $ POST /Something
  $ POST /SomethingElse
  ...

Sweet! Much better.

Exit Status

Successful requests (HTTP respose with 2xx status) return zero. Otherwise, the first digit of the response status is returned (i.e., 1 for 1xx, 3 for 3xx, 4 for 4xx, etc.) This is because the exit status is an 8 bit integer---it can't be greater than 255. If you want the exact status code you can always just pass the -v option to curl.

Using Resty In Shell Scripts

Since resty creates the REST verb functions in the shell, when using it from a script you must source it before you use any of the functions. However, it's likely that you don't want it to be overwriting the resty host history file, and you will almost always want to set the URI base explicitly.

  #!/usr/bin/env bash

  # Load resty, don't write to the history file, and set the URI base
  . /path/to/resty -W 'https://myhost.com/data*.json'

  # GET the JSON list of users, set each of their 'disabled' properties
  # to 'false', and PUT the modified JSON back
  GET /users | jsawk 'this.disabled = false' | PUT

Here the -W option was used when loading the script to prevent writing to the history file and an initial URI base was set at the same time. Then a JSON file was fetched, edited using jsawk, and re-uploaded to the server.

To assign the response of resty to a variable you can you do for example: VAR="$(GET /some/request)". Note that the quote symbol (") around the subcommand is necessary if the output contains spaces.

Working With JSON or XML Data

JSON REST web services require some special tools to make them accessible and easily manipulated in the shell environment. The following are a few scripts that make dealing with JSON data easier.

  • The included pp script will pretty-print JSON for you. You just need to install the JSON perl module from CPAN (included with brew install) or you can use pypp if you have python installed.

    GET /blogs.json | pp # pretty-prints the JSON output from resty

  • You can use powerful jq Json command line processor to perform operations on the received json. just pyping to jq . will pretty print the json in color

  • Another way to format JSON output:

    $ echo '{"json":"obj"}' | python -mjson.tool
    {
      "json": "obj"
    }
    
  • Jsawk can be used to process and filter JSON data from and to resty, in a shell pipeline. This takes care of parsing the input JSON correctly, rather than using regexes and sed, awk, perl or the like, and prints the resulting output in correct JSON format, as well.

    GET /blogs.json | jsawk -n 'out(this.title)' # prints all the blog titles

  • The tidy tool can be used to format HTML/XML:

    $ ~$ echo "<test><deep>value</deep></test>" | tidy -xml -q -i
    <test>
      <deep>value</deep>
    </test>
    

resty's People

Contributors

aars avatar adamv avatar adrieankhisbe avatar amitaibu avatar aroscoe avatar cyberhuman avatar extremeshok avatar jparagon avatar mattstevens avatar micha avatar namelessjon avatar padthaitofuhot avatar pcl avatar trentm 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  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

resty's Issues

Performance in cygwin

Resty is 2 orders of magnitude slower then POCurl on cygwin. A request that takes 7 millis to get back using curl takes 700 millis with resty (same exact options).

(Will provide traces tomorrow...)

resty fails silenty with self-signed certs (-k)

I was struggling to understand why resty was silent on all commands, no error, no output.

GET /
GET /agents
POST /

etc.. just returned immediately. SO I poked with curl and forget the app was self-signed.

curl -L https://mysite.com
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

adding -k to the resty initialize call fixed everything.

THis critical error from curl should be presented to the user when initializing resty.

Parse redirection correctly and accept HTTP 1.0 response

Here is a very quick fix to make resty accept HTTP 1.0 responses too and make it deal correctly with redirections. (always take the last response code.)
Turn

    |sed '/^.*HTTP\/1\.1 [0-9][0-9][0-9]/s/.*\([0-9]\)[0-9][0-9].*/\1/p; d')

into

    |sed '/^.*HTTP\/1\.[01] [0-9][0-9][0-9]/s/.*\([0-9]\)[0-9][0-9].*/\1/p; d' | tail -n1)

Requests that return "<url> malformed" also return last request's response

If you:

resty http://localhost:5984
GET /test

It returns the expected result (information about the CouchDB database I'm getting info about).

However, if I do that, and then type it again--forgetting the opening slash:

GET test

I get:

* <url> malformed
* <url> malformed
* getaddrinfo(3) failed for test:80
* Couldn't resolve host 'test'
* Closing connection #0
* About to connect() to localhost port 5984 (#0)
*   Trying 127.0.0.1... connected

and the remainder (headers and content) of my earlier request.

What I'd expect is the "Couldn't resolve host 'test'" response.

Thanks.

GET needs -G to pass query string parameters

The GET command currently needs -G to work with query string parameters. My understanding of curl is that if -d is used without -G curl switches to POST instead. Shouldn't resty always use -G with the GET command?

Current resty fails completely in zsh

I just downloaded resty and it doesn't work at all for me with zsh:

$ . resty
$ resty 'http://localhost:4984'
http://localhost:4984*
$ GET /
curl: (3) <url> malformed

I've got zsh 4.3.11 on Mac OS X 10.8.2.

Unfortunately my shell-scripting fu is very low, so I don't know how to go about debugging this. No doubt it's some arcane difference in quoting between bash and zsh...

Flags not passed to curl

It seems that the flags are not passed to curl correctly. They are ignored:

$ resty http://localhost:8000                                    
http://localhost:8000*
$ GET /Blah
<?xml version="1.0"?><data>...</data>
$ GET /vehicle/ybinfo -H "Accept: application/json"
<?xml version="1.0"?><data>...</data>

Compared to curl:

$ curl http://localhost:8000/Blah
<?xml version="1.0"?><data>...</data>
$ curl http://localhost:8000/Blah -H "Accept: application/json"
{"data": ...} 

Using resty 1.3 under zsh 4.3.9 (i386-apple-darwin10.0) on OS X 10.6.6.

Resty adding \n@- to POST body

Just installed resty on my laptop and when I try using POST it always appends \n@- to the body. This of course results in some nasty deserialization errors. Any ideas on what it might be?

Added a help section

Hi, not sure if you want it, but I added -h (or --help) option to your script.
The patch itself probably has more than you want because I change the indents per Google's shell style guide :)

diff --git a/resty b/resty
index 87fbed4..aba0e43 100755
--- a/resty
+++ b/resty
@@ -1,4 +1,3 @@
-#
 # resty - A tiny command line REST interface for bash and zsh.
 #
 # Fork me on github:
@@ -7,114 +6,128 @@
 # Author:
 #   Micha Niskin <[email protected]>
 #   Copyright 2009, no rights reserved.
+#
+#   Modified by Clayton Dukes <[email protected]>
+#   https://github.com/claytondukes
+#   Added -h or --help option
+#   Reformatted using Google's Style Guide
+#   http://google-styleguide.googlecode.com/svn/trunk/shell.xml?showone=Indentation#Indentation
 #

+
 export _resty_host=""
 export _resty_path=""
 export _resty_nohistory=""

+
 function resty() {
   local confdir datadir host cookies method h2t editor domain _path opt dat res ret out err verbose raw i j d tmpf args2 wantdata vimedit quote query maybe_query
-  local -a curlopt
-  local -a curlopt2
-
-  if [ -n "$XDG_CONFIG_HOME" ]; then
-    confdir="$XDG_CONFIG_HOME/resty"
-    datadir="$XDG_DATA_HOME/resty"
-  else
-    confdir="$HOME/.resty"
-    datadir="$confdir"
-  fi
-  mkdir -p "$confdir"
-  host="$datadir/host"
-  cookies="$datadir/c"
-  method="$1"; [[ $# > 0 ]] && shift
-  h2t=$((exec 2>&-; (which lynx >/dev/null && echo lynx -stdin -dump) \
-                || which html2text || which cat) |tail -n 1)
-  editor=$((exec 2>&-; which "$EDITOR" || which vim || echo "vi") |tail -n 1)
-
-  [ "${method#P}" != "$method" ] || [ "$method" = "TRACE" ] && wantdata="yes"
-
-  [ -d "$cookies" ] || (mkdir -p "$cookies"; echo "http://localhost*" > "$host")
-  [ -n "$1" ] && [ "${1#/}" != "$1" ] \
-    && _path="$1" && [[ $# > 0 ]] && shift
-  [ "$1" = "${1#-}" ] && dat="$1" && [[ $# > 0 ]] && shift
-
-  j=1
-  for i in "$@"; do
-    [ -n "$maybe_query" -a -z "$query" ] && query="?$i" && continue
-    ([ "$i" = "--verbose" ] || echo "$i" | grep '^-[a-zA-Z]*v[a-zA-Z]*$' >/dev/null) \
-      && verbose="yes" && continue
-    [ "$i" = "-V" ] && vimedit="yes" && continue
-    [ "$i" = "-Z" ] && raw="yes" && continue
-    [ "$i" = "-W" ] && continue
-    [ "$i" = "-Q" ] && quote="yes" && continue
-    [ "$i" = "-q" ] && maybe_query="yes" && continue
-    curlopt[j]="$i" && j=$((j + 1))
-  done
-
-  [ -z "$quote" ] && _path=$(echo "$_path"|sed 's/%/%25/g;s/\[/%5B/g;s/\]/%5D/g;s/|/%7C/g;s/\$/%24/g;s/&/%26/g;s/+/%2B/g;s/,/%2C/g;s/:/%3A/g;s/;/%3B/g;s/=/%3D/g;s/?/%3F/g;s/@/%40/g;s/ /%20/g;s/#/%23/g;s/{/%7B/g;s/}/%7D/g;s/\\/%5C/g;s/\^/%5E/g;s/~/%7E/g;s/`/%60/g')
-
-  [ "$method" = "HEAD" ] || [ "$method" = "OPTIONS" ] && raw="yes"
-  [ -z "$_resty_host" ] && _resty_host=$(cat "$host" 2>/dev/null)
-  [ "$method" = "-v" ] && echo "$_resty_host $_resty_opts" && return
-  [ -z "$method" ] && echo "$_resty_host" && return
-  [ -n "$_path" ] && _resty_path=$_path
-  domain=$(echo -n "$_resty_host" \
-    |perl -ane '/^https?:\/\/([^\/\*]+)/; print $1')
-  _path="${_resty_host//\*/$_resty_path}"
+    local -a curlopt
+    local -a curlopt2
+
+# cdukes: Added help
+    if echo "$@" | egrep -q -e '(-h)|(--help)'; then
+      HELP
+        shift
+        return 1
+        fi
+        if [ -n "$XDG_CONFIG_HOME" ]; then
+          confdir="$XDG_CONFIG_HOME/resty"
+            datadir="$XDG_DATA_HOME/resty"
+        else
+          confdir="$HOME/.resty"
+            datadir="$confdir"
+            fi
+            mkdir -p "$confdir"
+            host="$datadir/host"
+            cookies="$datadir/c"
+            method="$1"; [[ $# > 0 ]] && shift
+            h2t=$((exec 2>&-; (which lynx >/dev/null && echo lynx -stdin -dump) \
+                  || which html2text || which cat) |tail -n 1)
+            editor=$((exec 2>&-; which "$EDITOR" || which vim || echo "vi") |tail -n 1)
+
+            [ "${method#P}" != "$method" ] || [ "$method" = "TRACE" ] && wantdata="yes"
+
+            [ -d "$cookies" ] || (mkdir -p "$cookies"; echo "http://localhost*" > "$host")
+            [ -n "$1" ] && [ "${1#/}" != "$1" ] \
+            && _path="$1" && [[ $# > 0 ]] && shift
+            [ "$1" = "${1#-}" ] && dat="$1" && [[ $# > 0 ]] && shift
+
+            j=1
+            for i in "$@"; do
+              [ -n "$maybe_query" -a -z "$query" ] && query="?$i" && continue
+                ([ "$i" = "--verbose" ] || echo "$i" | grep '^-[a-zA-Z]*v[a-zA-Z]*$' >/dev/null) \
+                && verbose="yes" && continue
+                [ "$i" = "-V" ] && vimedit="yes" && continue
+                [ "$i" = "-Z" ] && raw="yes" && continue
+                [ "$i" = "-W" ] && continue
+                [ "$i" = "-Q" ] && quote="yes" && continue
+                [ "$i" = "-q" ] && maybe_query="yes" && continue
+                curlopt[j]="$i" && j=$((j + 1))
+                done
+
+                [ -z "$quote" ] && _path=$(echo "$_path"|sed 's/%/%25/g;s/\[/%5B/g;s/\]/%5D/g;s/|/%7C/g;s/\$/%24/g;s/&/%26/g;s/+/%2B/g;s/,/%2C/g;s/:/%3A/g;s/;/%3B/g;s/=/%3D/g;s/?/%3F/g;s/@/%40/g;s/ /%20/g;s/#/%23/g;s/{/%7B/g;s/}/%7D/g;s/\\/%5C/g;s/\^/%5E/g;s/~/%7E/g;s/`/%60/g')
+
+                [ "$method" = "HEAD" ] || [ "$method" = "OPTIONS" ] && raw="yes"
+                [ -z "$_resty_host" ] && _resty_host=$(cat "$host" 2>/dev/null)
+                [ "$method" = "-v" ] && echo "$_resty_host $_resty_opts" && return
+                [ -z "$method" ] && echo "$_resty_host" && return
+                [ -n "$_path" ] && _resty_path=$_path
+                domain=$(echo -n "$_resty_host" \
+                    |perl -ane '/^https?:\/\/([^\/\*]+)/; print $1')
+                _path="${_resty_host//\*/$_resty_path}"

   case "$method" in
-    HEAD|OPTIONS|GET|DELETE|POST|PUT|PATCH|TRACE)
-      eval "curlopt2=(${_resty_opts[*]})"
-      dat=$( ( [ "$wantdata" = "yes" ] \
-        && ( ( [ -n "$dat" ] && echo "$dat") \
-        || ([ ! -t 0 ] && echo "@-") ) ) || echo)
-      if [ "$wantdata" = "yes" ] && [ "$vimedit" = "yes" ]; then
-        tmpf=$(mktemp /tmp/resty.XXXXXX)
-        [ -t 0 ] || cat > $tmpf
-        (exec < /dev/tty; "$editor" $tmpf)
-        dat=$(cat $tmpf)
-        rm -f $tmpf
-      fi
-      [ -n "$dat" ] && [ "$dat" != "@-" ] && [[ $# > 0 ]] && shift
-      [ "$1" = "-Z" ] && raw="yes" && [[ $# > 0 ]] && shift
-      [ -n "$dat" ] && opt="--data-binary"
-      [ "$method" = "HEAD" ] && opt="-I" && raw="yes"
-      [ -f "$confdir/$domain" ] && eval "args2=( $(cat "$confdir/$domain" 2>/dev/null |sed 's/^ *//' |grep ^$method |cut -b $((${#method}+2))-) )"
-      res=$((((curl -sLv $opt "$dat" -X $method \
-              -b "$cookies/$domain" -c "$cookies/$domain" \
-              "${args2[@]}" "${curlopt2[@]}" "${curlopt[@]}" "$_path$query" \
-        |sed 's/^/OUT /' && echo) 3>&2 2>&1 1>&3) \
-        |sed 's/^/ERR /' && echo) 2>&1)
-      out=$(echo "$res" |sed '/^OUT /s/^....//p; d')
-      err=$(echo "$res" |sed '/^ERR /s/^....//p; d')
-      ret=$(echo "$err" |sed \
-        '/^.*HTTP\/1\.[01] [0-9][0-9][0-9]/s/.*\([0-9]\)[0-9][0-9].*/\1/p; d' \
-        | tail -n1)
-      [ -n "$err" -a -n "$verbose" ] && echo "$err" 1>&2
-      echo "$err" | grep -i '^< \s*Content-Type:  *text/html' >/dev/null \
-        && [ -z "$raw" ] && d=$h2t || d=cat
-      [ -n "$out" ] && out=$(echo "$out" |eval "$d")
-      [ "$d" != "${d##lynx}" ] && out=$(echo "$out" |perl -e "\$host='$(echo "$_resty_host" |sed 's/^\(https*:\/\/[^\/*]*\).*$/\1/')';" -e '@a=<>; $s=0; foreach (reverse(@a)) { if ($_ =~ /^References$/) { $s++; } unless ($s>0) { s/^\s+[0-9]+\. //; s/^file:\/\/localhost/$host/; } push(@ret,$_); } print(join("",reverse(@ret)))')
-      if [ "$ret" != "2" ]; then
-        [ -n "$out" ] && echo "$out" 1>&2
-        return $ret
-      else
-        [ -n "$out" ] && echo "$out"
-      fi
-      ;;
-    http://*|https://*)
-      _resty_opts=$(printf '%q ' "${curlopt[@]}")
-      export _resty_opts
-      echo "$method" |grep '\*' >/dev/null || method="${method}*"
-      (echo "$method" |tee "${_resty_nohistory:-$host}") |cat 1>&2 \
-        && _resty_host="$method"
-      ;;
-    *)
-      resty "http://$method" "${curlopt[@]}"
-      ;;
-  esac
+                HEAD|OPTIONS|GET|DELETE|POST|PUT|PATCH|TRACE)
+                  eval "curlopt2=(${_resty_opts[*]})"
+                  dat=$( ( [ "$wantdata" = "yes" ] \
+                        && ( ( [ -n "$dat" ] && echo "$dat") \
+                          || ([ ! -t 0 ] && echo "@-") ) ) || echo)
+                  if [ "$wantdata" = "yes" ] && [ "$vimedit" = "yes" ]; then
+                    tmpf=$(mktemp /tmp/resty.XXXXXX)
+                      [ -t 0 ] || cat > $tmpf
+                      (exec < /dev/tty; "$editor" $tmpf)
+                      dat=$(cat $tmpf)
+                      rm -f $tmpf
+                      fi
+                      [ -n "$dat" ] && [ "$dat" != "@-" ] && [[ $# > 0 ]] && shift
+                      [ "$1" = "-Z" ] && raw="yes" && [[ $# > 0 ]] && shift
+                      [ -n "$dat" ] && opt="--data-binary"
+                      [ "$method" = "HEAD" ] && opt="-I" && raw="yes"
+                      [ -f "$confdir/$domain" ] && eval "args2=( $(cat "$confdir/$domain" 2>/dev/null |sed 's/^ *//' |grep ^$method |cut -b $((${#method}+2))-) )"
+                      res=$((((curl -sLv $opt "$dat" -X $method \
+                                -b "$cookies/$domain" -c "$cookies/$domain" \
+                                "${args2[@]}" "${curlopt2[@]}" "${curlopt[@]}" "$_path$query" \
+                                |sed 's/^/OUT /' && echo) 3>&2 2>&1 1>&3) \
+                            |sed 's/^/ERR /' && echo) 2>&1)
+                      out=$(echo "$res" |sed '/^OUT /s/^....//p; d')
+                      err=$(echo "$res" |sed '/^ERR /s/^....//p; d')
+                      ret=$(echo "$err" |sed \
+                          '/^.*HTTP\/1\.[01] [0-9][0-9][0-9]/s/.*\([0-9]\)[0-9][0-9].*/\1/p; d' \
+                          | tail -n1)
+                      [ -n "$err" -a -n "$verbose" ] && echo "$err" 1>&2
+                      echo "$err" | grep -i '^< \s*Content-Type:  *text/html' >/dev/null \
+                      && [ -z "$raw" ] && d=$h2t || d=cat
+                      [ -n "$out" ] && out=$(echo "$out" |eval "$d")
+                      [ "$d" != "${d##lynx}" ] && out=$(echo "$out" |perl -e "\$host='$(echo "$_resty_host" |sed 's/^\(https*:\/\/[^\/*]*\).*$/\1/')';" -e '@a=<>; $s=0; foreach (reverse(@a)) { if ($_ =~ /^References$/) { $s++; } unless ($s>0) { s/^\s+[0-9]+\. //; s/^file:\/\/localhost/$host/; } push(@ret,$_); } print(join("",reverse(@ret)))')
+                      if [ "$ret" != "2" ]; then
+                        [ -n "$out" ] && echo "$out" 1>&2
+                          return $ret
+                      else
+                        [ -n "$out" ] && echo "$out"
+                          fi
+                          ;;
+http://*|https://*)
+                _resty_opts=$(printf '%q ' "${curlopt[@]}")
+                  export _resty_opts
+                  echo "$method" |grep '\*' >/dev/null || method="${method}*"
+                  (echo "$method" |tee "${_resty_nohistory:-$host}") |cat 1>&2 \
+                  && _resty_host="$method"
+                  ;;
+                *)
+                  resty "http://$method" "${curlopt[@]}"
+                  ;;
+                esac
 }

 function HEAD() {
@@ -151,4 +164,38 @@ function TRACE() {

 [ "$1" = "-W" ] && export _resty_nohistory="/dev/null" && [[ $# > 0 ]] && shift

+
+# Help function
+# Set fonts for Help.
+NORM=`tput sgr0`
+BOLD=`tput bold`
+REV=`tput smso`
+function HELP () {
+  printf "\n\t\t%s\n" "Help documentation for ${BOLD}Resty${NORM}"
+    printf "%s\n" "${REV}Basic usage:${NORM}"
+    printf "\t%s\n" "resty [-W] [remote]           # load functions into shell"
+    printf "\t%s\n" "resty [-v]                              # prints current request URI base"
+    printf "\t%s\n" "resty <remote> [OPTIONS]                # sets the base request URI"
+    printf "\t%s\n" "HEAD [path] [OPTIONS]                 # HEAD request"
+    printf "\t%s\n" "OPTIONS [path] [OPTIONS]                # OPTIONS request"
+    printf "\t%s\n" "GET [path] [OPTIONS]                    # GET request "
+    printf "\t%s\n" "DELETE [path] [OPTIONS]                 # DELETE request "
+    printf "\t%s\n" "PUT [path] [data] [OPTIONS]             # PUT request"
+    printf "\t%s\n" "PATCH [path] [data] [OPTIONS]           # PATCH request"
+    printf "\t%s\n" "POST [path] [data] [OPTIONS]            # POST request"
+    printf "\t%s\n" "TRACE [path] [OPTIONS]                  # TRACE request"
+
+    printf "\n%s\n" "${REV}Options:${NORM}"
+    printf "\t%s\n" "${REV}-Q${NORM}  --Don't URL encode the path."
+    printf "\t%s\n" "${REV}-q <query>${NORM}  --Send query string with the path."
+    printf "\t%s\n" "  A ${BOLD}?${NORM} is prepended to ${BOLD}<query>${NORM} and concatenated onto the ${BOLD}<path>${NORM}."
+    printf "\t%s\n" "${REV}-W${NORM}  --Don't write to history file (only when sourcing script)."
+    printf "\t%s\n" "${REV}-V${NORM}  --Edit the input data interactively in 'vi'. ${BOLD}(PUT, PATCH,"
+    printf "\t%s\n" "      and POST${NORM} requests only, with data piped to stdin.)"
+    printf "\t%s\n" "${REV}-Z${NORM}  --Raw output. This disables any processing of HTML in the response."
+    printf "\t%s\n" "${REV}-v${NORM}  --Verbose output. When used with the resty command itself"
+    printf "\t%s\n" "      this prints the saved curl options along with the current"
+    printf "\t%s\n" "      URI base. Otherwise this is passed to curl for verbose curl output."
+    printf "\t%s\n" "${REV}<curl opt>${NORM}  --Any curl options will be passed down to curl."
+}
 resty "$@" >/dev/null 2>&1

Cannot change URL

When trying to change the URL with resty I get this error:

$ resty
http://localhost:8888*
$ resty http://10.153.2.224:8000
resty:80: bad substitution

Running:

$ brew info resty
resty 1.5
https://github.com/micha/resty
/usr/local/Cellar/resty/1.5 (4 files, 32K)
...
$ zsh --version
zsh 4.3.9 (i386-apple-darwin10.0)

OPTIONS does not add headers

When I add headers using -H "Header-Name: value" to the end of an OPTIONS command, the header isn't present in the request. To reproduce:

% resty http://www.w3c.org
% OPTIONS / -v -H "Origin: http://www.google.com/"
* <url> malformed
* <url> malformed
* About to connect() to www.w3c.org port 80 (#0)
*   Trying 128.30.52.45... connected
* Connected to www.w3c.org (128.30.52.45) port 80 (#0)
> OPTIONS / HTTP/1.1
> User-Agent: curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4 OpenSSL/0.9.8r zlib/1.2.5
> Host: www.w3c.org
> Accept: */*
> 
< HTTP/1.1 301 Moved Permanently
< Cache-Control: no-cache
< Content-length: 0
< Location: http://www.w3.org/
< Connection: close
...

Note that the "Origin" header is missing. This command works correctly:

% curl -X OPTIONS -H "Origin: http://www.google.com/" -v http://www.w3c.org/ 

* About to connect() to www.w3c.org port 80 (#0)
*   Trying 128.30.52.45... connected
* Connected to www.w3c.org (128.30.52.45) port 80 (#0)
> OPTIONS / HTTP/1.1
> User-Agent: curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4 OpenSSL/0.9.8r zlib/1.2.5
> Host: www.w3c.org
> Accept: */*
> Origin: http://www.google.com/
> 
< HTTP/1.1 301 Moved Permanently
< Cache-Control: no-cache
< Content-length: 0
< Location: http://www.w3.org/
< Connection: close

windows?

does not work on windows right?

Query Parameters for PUT and DELETE

First, Resty is fabulous! :) Thanks for building it.

Second, it'd be great if it were possible to pass query parameters to PUT and DELETE methods. I'd really love to be able to put them inline with the URL (ex: /url?param=value&other=value), but being able to use -d or similar would be fine at this point. Perhaps an alternative scheme would be a -q switch that could take a string of query parameters:
-q "param=value&other=value"

This feature would make working with CouchDB a good bit easier given it's need for "rev=1-...." whenever PUT-ing or DELETE-ing documents or attachments. I'm getting around it now using -H "If-Match: 1-..." (the Etag-based solution), but there are likely other API's that aren't that flexible.

Thanks for considering this idea,
Benjamin

Warns in zsh

wanderlust [319] ~/code/dotfiles «master» $ resty 'http://localhost:5000'
http://localhost:5000*
wanderlust [320] ~/code/dotfiles «master» $ GET /
(eval):91: unmatched `
["milk","water","gin"]

Get the raw cURL command

I use resty mostly in development. When I figure out what my request is, however, I need to get the raw cURL command for use in a script that will run in another environment where resty is not available. Is there way to output the entire cURL command that's being executed under the covers? If not, that would be a helpful feature.

DELETE request with a payload?

Hello,

I know that as this is vaguely touched in the HTTP spec, most REST tools are very touchy about this subject: some disallow completely such behaviour, and resty seems to ignore any payload given along a DELETE request. So is this an issue or works as designed? Thanks!

Setting default query string for every request

I am trying to set default query string to be passed for every request but it's not picking up

resty https://api.hipchat.com/v2 -H "Content-Type: application/json" -q "auth_token=ASD"

Allow default resty options

I'd really like the ability to specify default resty options. I'm lazy and in certain cases I would like to always be able to type URLs in the same way that I specify them in my browser. For example I'd like the following scenario to work:

$ resty http://localhost:8080
resty http://localhost:8080*

$ # This won't actually work...
$ GET '/jane?rev=1'
<some error from the server>

$ # Instead you need to do...
$ GET '/jane?rev=1' -Q
{ "_id": "jane", "active": "true", ... }

$ # Or you can do...
$ GET '/jane' -q 'rev=1'
{ "_id": "jane", "active": "true", ... }

Ideally you'd be able to tell resty when you specify the URI base (or perhaps through a configuration file in ~/.resty) that you want all GET commands to include resty's -Q option. I'm not quite sure what the syntax should be for that though. I'd be perfectly happy if it was buried inside of a config file somewhere and not available to be set via the command line during the URI base specification.

Think it's reasonable to add something like this?

Cannot use -H under zsh

$ resty http://localhost:8000
http://localhost:8000*
$ GET /Blah
<?xml version="1.0"?><data>...</data>
$ GET /Blah -H "Accept: application/json"
resty:25: curlopt: assignment to invalid subscript range

I'm running zsh zsh 4.3.9 (i386-apple-darwin10.0) and resty 1.2.

resty script not self-documenting

resty (the script itself) does not include any information indicating where it came from. It would be useful if one of the first lines of the script contained the URL of resty's homepage, so it can be found again an upgraded in months or years.

Cannot POST or PUT JSON data without Content-type Header

As per the following example, given in the README
POST /blogs.json '{"title" : "new post", "body" : "This is the new new."}'
it should work without setting Content-type Header. But it doesn't.

Example:
When the POST request is as follows
POST /creator/files.json '{ "attributes": [ {"title": "New Book" } ] }'
This is how Rails receives the parameter
Parameters: {"{ \"attributes\": "=>{" {\"title\": \"New Book\" } "=>{" }"=>nil}}}
The scenario remains the same when the input is read from a file or pipe
echo '{ "attributes": [ {"title": "New Book" } ] }' | POST /creator/files.json

But when the POST request is made with Content-type as follows
POST /creator/files.json '{ "attributes": [ {"title": "New Book" } ] }' -H 'Content-type: application/json'
Rails receives the parameters properly as,
{"attributes"=>[{"title"=>"New Book"}]}

Please add Content-type: application/json Header automatically if the URL ends with .json. Though I am not sure if this is applicable only for Rails.

nested restful route is not working

I believe this is a bug. Making a GET request using Resty to a URI that has a nested resource does not make the request to the full URI. Am I calling the resty command wrong?

The uri of a nested resource:

$ URI=http://localhost:3000/users/user003/skills/7385140.json

$ echo $URI
http://localhost:3000/users/user003/skills/7385140.json

Using Resty

$ resty GET $URI -H "SomeAccessToken: $TOKEN" | jshon
{
 "skills": [
  {
   ...
  }
 ]
}

The server log:

Started GET "/users/user003/skills.json" for 127.0.0.1 at 2012-07-24 10:34:59 -0500
Processing by Users::SkillsController#index as JSON
  Parameters: {"user_id"=>"user003"}
Completed 200 OK in 2ms (Views: 0.4ms)

Using Curl

The same request using curl.

$ curl $URI -H "IM-AccessToken: $TOKEN" | jshon
{
 "skill": {
  ...
 }
}

The server log:

Started GET "/users/user003/skills/7385140.json" for 127.0.0.1 at 2012-07-24 10:36:15 -0500
Processing by Users::SkillsController#show as JSON
  Parameters: {"user_id"=>"user003", "id"=>"7385140"}
Completed 200 OK in 2ms (Views: 0.4ms)

$accp/$acpt

the accept headers variable used in the methods ($accp) is declared as 'acpt' on line 5

Warns in zsh

wanderlust [319] ~/code/dotfiles «master» $ resty 'http://localhost:5000'
http://localhost:5000*
wanderlust [320] ~/code/dotfiles «master» $ GET /
(eval):91: unmatched `
["milk","water","gin"]

OPTIONS don't show the allowed methods

$ resty http://localhost:5000
http://localhost:5000*
$ OPTIONS
$ OPTIONS -v
* <url> malformed
* Closing connection -1
* <url> malformed
* Closing connection -1
* About to connect() to localhost port 5000 (#0)
*   Trying ::1...
* Adding handle: conn: 0x7fdc09806200
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7fdc09806200) send_pipe: 1, recv_pipe: 0
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 5000 (#0)
> OPTIONS / HTTP/1.1
> User-Agent: curl/7.31.0
> Host: localhost:5000
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Content-Type: text/html; charset=utf-8
< Allow: HEAD, OPTIONS, GET
< Content-Length: 0
< Server: Werkzeug/0.9.1 Python/2.7.5
< Date: Fri, 05 Jul 2013 12:24:35 GMT
<
* Closing connection 0

Odd Behavior with '-v' Flag

I was having a bit of trouble this morning. Basically when I use the -v flag Resty won't respect the URL and other such things I pass in and instead will re-run the last command which did not include the flag. See below. Pretty unexpected behavior and seems contrary to the docs. Doesn't seem to me this would be useful considering many operations may not be idempotent.

Robs-MacBook-Pro:bin rob$ GET /easternhhc_test_t4/current_failures/_count
{"count":18,"_shards":{"total":5,"successful":5,"failed":0}}
Robs-MacBook-Pro:bin rob$ GET -v /easternhhc_test_t4/current_failures/_status
* <url> malformed
* <url> malformed
* <url> malformed
* About to connect() to ec2-174-129-47-132.compute-1.amazonaws.com port 443 (#0)
*   Trying 174.129.47.132...
* connected
* Connected to ec2-174-129-47-132.compute-1.amazonaws.com (174.129.47.132) port 443 (#0)
* SSLv3, TLS handshake, Client hello (1):
} [data not shown]
* SSLv3, TLS handshake, Server hello (2):
{ [data not shown]
* SSLv3, TLS handshake, CERT (11):
{ [data not shown]
* SSLv3, TLS handshake, Server key exchange (12):
{ [data not shown]
* SSLv3, TLS handshake, Server finished (14):
{ [data not shown]
* SSLv3, TLS handshake, Client key exchange (16):
} [data not shown]
* SSLv3, TLS change cipher, Client hello (1):
} [data not shown]
* SSLv3, TLS handshake, Finished (20):
} [data not shown]
* SSLv3, TLS change cipher, Client hello (1):
{ [data not shown]
* SSLv3, TLS handshake, Finished (20):
{ [data not shown]
* SSL connection using DHE-RSA-AES256-SHA
* Server certificate:
*    subject: C=US; ST=California; L=San Jose; O=DeVero; OU=Eng; CN=*.amazonaws.com
*    start date: 2013-08-08 22:58:30 GMT
*    expire date: 2014-08-08 22:58:30 GMT
*    common name: *.amazonaws.com (matched)
*    issuer: C=US; ST=California; L=San Jose; O=DeVero; OU=Eng; CN=*.amazonaws.com
*    SSL certificate verify result: self signed certificate (18), continuing anyway.
* Server auth using Basic with user 'dauser'
> GET /easternhhc_test_t4/current_failures/_count HTTP/1.1
> Authorization: Basic bWFtMcc3czNhbkMwbm1zcnk6ejB0YXBlckBzM3QwcmVtM21iM3I=
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8y zlib/1.2.5
> Host: ec2-174-129-47-132.compute-1.amazonaws.com
> Accept: */*
> 
< HTTP/1.1 200 OK
< Server: nginx/1.1.19
< Date: Wed, 22 Jan 2014 18:38:42 GMT
< Content-Type: application/json; charset=UTF-8
< Content-Length: 60
< Connection: keep-alive
< 
{ [data not shown]
* Connection #0 to host ec2-174-129-47-132.compute-1.amazonaws.com left intact
* Closing connection #0
* SSLv3, TLS alert, Client hello (1):
} [data not shown]
{"count":18,"_shards":{"total":5,"successful":5,"failed":0}}

Cache the host options

When changin host, read options per method once and for all and store it has a shell variable

'-W' needs to be *after* URL prefix argument. README says otherwise.

Hello,

At least for me on a Solaris box I've found that this example in the README doesn't work:

. /path/to/resty -W 'https://myhost.com/data*.json'

For the equivalent to work for me, I needed to use the '-W' after the URL prefix argument like so:

. /path/to/resty 'https://myhost.com/data*.json' -W

A concrete example: Here I've added an "echo" statement to show the 'curl' command-line that is being called. Hopefully that gives you enough of a hint:

[root@mybox ~]# . resty/resty -W 'http://10.99.99.8:8080*'
[root@mybox ~]# GET /
curl -sLv  -X GET -b /root/.resty/c/-W -c /root/.resty/c/-W http://-W/
[root@mybox ~]# . resty/resty  'http://10.99.99.8:8080*' -W
[root@mybox ~]# GET /
curl -sLv  -X GET -b /root/.resty/c/10.99.99.8:8080 -c /root/.resty/c/10.99.99.8:8080 http://10.99.99.8:8080/
<errors>
  <error>Not authorized
</error>
</errors>
[root@mybox ~]# 

Where, in my case that "..." XML output is the expected response.

Ideas? It is possible this is a Solaris vs. Linux difference, but I haven't traced through the Bash code path handling '-W'.

urls inside urls

I use urls as my couchdb keys (maybe this is dumb, but nevermind). so I need to do things like

PUT "/$url"

with resty.

You say on your documentation that I need to escape /; all the rest, resty will handle. I substituted / to %2F on $url. but it saves with %2F on the key name, not /; somehow resty is also escaping %, where it shouldn't.

PUT '/http:%2F%2Fwww.test.com' '{"a": 5}'
{"ok":true,"id":"http:%2F%2Fwww.test.com","rev":"1-8bf226e57847cf49b0d45065383cf323"}

(should return "id":"http://www.test.com")

sending unescaped obviously doesn't help

PUT '/http://www.test.com' '{"a": 5}'
{"ok":true,"id":"http:","rev":"1-c04faa654c092ab691c6d82f2b57f90d"}

you say -Q prevents escaping. but then somehow www.test.com is saved as an attachment

PUT -Q '/http:%2F%2Fwww.test.com' '{"a": 5}'
{"ok":true,"id":"http:","rev":"1-38668c8ceb94ab26818d36f8139af49c"}
GET '/http:'
{"_id":"http:","_rev":"1-38668c8ceb94ab26818d36f8139af49c","_attachments":{"www.test.com":{"content_type":"application/octet-stream","revpos":1,"length":0,"stub":true}}}

unfortunately your -v shows the curl response, but not the curl command line. I was able to see it using an (ugly) custom debug. then I figured out a workaround for my case:

curl -X PUT "http://127.0.0.1/dbname/$urlwithslashesescaped" -d "$newdoc"

so, long story short, after struggling with resty for a while, I opted to use curl directly for this request (but I'm still using resty for my other requests)

I know my case is edgy so I don't know what your tool could do for me. I produced a patch that shows curl command line with resty -v

ps: this resty tool (and jsawk) is awesome!

From 94b608b03473f2a84eb36f7314f6612611fea563 Mon Sep 17 00:00:00 2001
From: Elias Amaral <[email protected]>
Date: Fri, 23 Dec 2011 23:25:35 -0300
Subject: [PATCH] adding curl command line to resty -v

---
 resty |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/resty b/resty
index 231155f..6111db2 100755
--- a/resty
+++ b/resty
@@ -82,6 +82,9 @@ function resty() {
       [ -n "$dat" ] && opt="--data-binary"
       [ "$method" = "HEAD" ] && opt="-I" && raw="yes"
       eval "args2=( $(cat "$confdir/$domain" 2>/dev/null |sed 's/^ *//' |grep ^$method |cut -b $((${#method}+2))-) )"
+   [[ $verbose ]] && echo curl -sLv $opt "$dat" -X $method \
+              -b "$cookies/$domain" -c "$cookies/$domain" \
+              "${args2[@]}" "${curlopt2[@]}" "${curlopt[@]}" "$_path$query" $'\n' 1>&2
       res=$((((curl -sLv $opt "$dat" -X $method \
               -b "$cookies/$domain" -c "$cookies/$domain" \
               "${args2[@]}" "${curlopt2[@]}" "${curlopt[@]}" "$_path$query" \
-- 
1.7.5.4

HTTPS Connection

Could you please document how to use RESTY over an https connection? I assume this capability is there since its a wrapper for CURL.

GET/POST

GET/POST calls overlap libwww-perl (debian/ubuntu systems) package

Helper Flags for content

Add flags such as -j/--json --xml ash shortcut to set the headers on curl for content negociation

A way to make password information not visible

I really love this tool, but I would love it even more if there was a way to enter basic authentication information in such a way that it wasn't put in my bash history. Any suggestions on how this could be done?

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.