#!/usr/bin/env python3

from __future__ import print_function

"""REST: Simple command line interface to testing RESTful services.

usage: REST [-h] [--cookie COOKIE] [--header HEADER] [--data DATA]
            {GET,POST,PUT,PATCH,DELETE} url

REST API Tester

positional arguments:
  {GET,POST,PUT,PATCH,DELETE}
                        The HTTP method to use
  url                   The URL to request

optional arguments:
  -h, --help            show this help message and exit
  --cookie COOKIE, -c COOKIE
                        Specify an HTTP cookie value in NAME=VALUE format.
  --header HEADER, -H HEADER
                        Add custom HTTP request headers in 'Name: Value'
                        format.
  --data DATA, -d DATA  JSON data to be sent with the request.

Examples:
    REST GET http://localhost/v1/resource/item
    REST POST http://localhost/v1/resource -d '{"hello": "world"}'
"""

import argparse
import requests
import json

def main():
    parser = argparse.ArgumentParser(description="REST API Tester")
    parser.add_argument(
        "--cookie", "-c",
        action="append",
        help="Specify an HTTP cookie value in NAME=VALUE format.",
    )
    parser.add_argument(
        "--header", "-H",
        action="append",
        help="Add custom HTTP request headers in 'Name: Value' format.",
    )
    parser.add_argument(
        "--data", "-d",
        default=None,
        help="JSON data to be sent with the request.",
    )
    parser.add_argument(
        "--insecure", "-k",
        action="store_true",
        help="Don't validate SSL certificates.",
    )
    parser.add_argument(
        "method",
        help="The HTTP method to use",
        choices=["GET", "POST", "PUT", "PATCH", "DELETE"],
    )
    parser.add_argument(
        "url",
        help="The URL to request",
    )
    args = parser.parse_args()

    # Convert cookie/header params.
    if args.header:
        args.header = strings_to_dict(args.header, ":")
    if args.cookie:
        args.cookie = strings_to_dict(args.cookie, "=")

    do_http(args)


def do_http(args):
    result = None

    headers = {
        "Content-Type": "application/json",
    }
    if args.header:
        headers.update(args.header)

    ssl_opts = {}
    if args.insecure:
        ssl_opts.update(verify=False)

    result = getattr(requests, args.method.lower())(
        args.url,
        headers=headers,
        cookies=args.cookie,
        data=args.data,
        **ssl_opts
    )

    print(args.method, args.url, result.status_code)

    # JSON response?
    try:
        parsed = result.json
        print(json.dumps(parsed,
            sort_keys=True,
            indent=4,
            separators=(',', ': '),
        ))
    except:
        print(result.text)


def strings_to_dict(strings, separator):
    """Turn a list of key/value pairs into a dictionary."""
    result = dict()
    for item in strings:
        k, v = item.split(separator)
        k = k.strip()
        v = v.strip()
        result[k] = v
    return result

if __name__ == "__main__":
    main()