Giter Site home page Giter Site logo

amareis / another-rest-client Goto Github PK

View Code? Open in Web Editor NEW
174.0 16.0 18.0 227 KB

Simple pure TypeScript REST API client that makes your code lesser and more beautiful than without it.

License: MIT License

JavaScript 52.40% TypeScript 47.60%
rest rest-client javascript typescript

another-rest-client's People

Contributors

amareis avatar felixlinker avatar vixalien 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

another-rest-client's Issues

SyntaxError: Unexpected token u in JSON at position 0

Hi there,

I tried using this library and following code yielded an error:

const RestClient = require('another-rest-client');
global.XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

let api = new RestClient('http://localhost:8082/engine-rest');
api.on('error', function(err) {
    console.log('err');
});
api.res('engine');
api.engine.get().then(function(result) {
    console.log(result);
}, function(reason) {
    console.log(reason);
});

When debugging the code in Visual Studio Code the promise resolved successfully with result being undefined. Also the error callback was not called.
The error displayed on the console is the following:

SyntaxError: Unexpected token u in JSON at position 0
    at parse (native)
    at safe (c:\Users\felix\Desktop\js-test\node_modules\another-rest-client\rest-client.js:80:17)
    at _createClass.value.xhr.onreadystatechange (c:\Users\felix\Desktop\js-test\node_modules\another-rest-client\rest-client.js:157:67)
    at exports.XMLHttpRequest.dispatchEvent (c:\Users\felix\Desktop\js-test\node_modules\xmlhttprequest\lib\XMLHttpRequest.js:591:25)
    at setState (c:\Users\felix\Desktop\js-test\node_modules\xmlhttprequest\lib\XMLHttpRequest.js:610:14)
    at IncomingMessage.<anonymous> (c:\Users\felix\Desktop\js-test\node_modules\xmlhttprequest\lib\XMLHttpRequest.js:447:13)
    at emitNone (events.js:91:20)
    at IncomingMessage.emit (events.js:185:7)
    at endReadableNT (_stream_readable.js:974:12)
    at _combinedTickCallback (internal/process/next_tick.js:80:11)

Trying the same query in postman works just fine. The result body is:

[{"name":"default"}]

With following headers:
Cache-Control →no-cache
Content-Type →application/json
Date →Mon, 05 Mar 2018 18:09:49 GMT
Transfer-Encoding →chunked

Especially as the promise resolves successfully I don't see me doing anything wrong. But if so I'd be happy to see my error pointed out to me.

Best regards
Felix

Concurrent requests with events

If you need, for example, get response headers, you can do so:

let pageLinks = {}
api.on('success', x => pageLinks.links = x.getResponseHeader('Link'))
let commits = await api.repos(action.repo.full_name).commits.get()
api.off('success')
console.log(pageLinks.links)

But it can be broken easily if another request emit success after this successevent, but before console.log. So we need method for attach event to strictly defined request, it's also fits #3

Axios instead XMLHttpRequest

I have some troubles with Authorization headers in XMLHttpRequest using Auth0. When I try to renew token from Auth0 after page loaded with this code:

api.on('request', xhr => {
  xhr.setRequestHeader('Authorization', `Bearer ${authResult.accessToken}`);
})

I expect that new token will replace the old one, but it's add like: Bearer OLDTOKEN, NEWTOKEN.

Can you help with replace XMLHttpRequest or provide example how to use tokens and when and how I should replace it?

ProgressEvent

Is it possible to get the progress of a (large) JSON response?

xhr spec
xhr example

Update:
I've tried implementing the example on whatwg.org, but no success. I don't see any calls to onprogress in my browser console. Would this be something provided by the server? (I'm using Python/Flask, and doing some research there also).

api.api().myapi()
    .get()
    .on('response', function(res) {
        console.log(res.onprogress) // returns 'null'
        res.onprogress = function(pe) {
           console.log(pe); // not reached
           if (pe.lengthComputable) {
               console.log(pe.loaded) // not reached
           }}})
     .then(function (_json) { do_stuff(_json) })

💡Can you add retry config to your amazing work?

Just like this (maybe like your awesome fluent api)
In this project: https://github.com/JustinBeckwith/retry-axios
and add methods like get, put, and so on doing their job.
source: https://github.com/JustinBeckwith/retry-axios
`raxConfig: {
// Retry 3 times on requests that return a response (500, etc) before giving up. Defaults to 3.
retry: 3,

// Retry twice on errors that don't return a response (ENOTFOUND, ETIMEDOUT, etc).
noResponseRetries: 2,

// Milliseconds to delay at first.  Defaults to 100. Only considered when backoffType is 'static'
retryDelay: 100,

// HTTP methods to automatically retry.  Defaults to:
// ['GET', 'HEAD', 'OPTIONS', 'DELETE', 'PUT']
httpMethodsToRetry: ['GET', 'HEAD', 'OPTIONS', 'DELETE', 'PUT'],

// The response status codes to retry.  Supports a double
// array with a list of ranges.  Defaults to:
// [[100, 199], [429, 429], [500, 599]]
statusCodesToRetry: [[100, 199], [429, 429], [500, 599]],

// If you are using a non static instance of Axios you need
// to pass that instance here (const ax = axios.create())
instance: ax,

// You can set the backoff type.
// options are 'exponential' (default), 'static' or 'linear'
backoffType: 'exponential',

// You can detect when a retry is happening, and figure out how many
// retry attempts have been made
onRetryAttempt: err => {
  const cfg = rax.getConfig(err);
  console.log(`Retry attempt #${cfg.currentRetryAttempt}`);
}

}`

Also there's another that has it's magic hidden like this:
https://github.com/softonic/axios-retry

Thanks in advance beacuse your awesome work

Cookie

I don't see any way to set withCredentials to true to make request with cookies

Abort XHR?

In current project I heavily use your library. Sometimes I need to abort opened xhr requests.

I think you could add one time event listeners. Look at this

...

let openedXHR = [];
api.once('request', (xhr) => {
    openedXHR.push(xhr);
})
api.res('account').res('balance').get().then(...)

openedXHR.forEach((xhr) => xhr.abort())

I can't use request event, because RestClient created once and reused everywhere.

Renew token

How to renew JWT token?
To set authorization token I using:

api.on('request', function(xhr) {
    xhr.setRequestHeader('Authorization', 'Bearer xxxTOKENxxx');
});

, but what I should do when get a new token?

Firefox: SyntaxError: JSON.parse: unexcepted...

var r = new RestClient('http://127.0.0.1:8080', {contentType: 'json'});
r.res('test')
r.test('ttt').get().then(function(k){alert(k)})

Chromium:
It works properly!

Firefox:
http://127.0.0.1:8080/test/ttt works properly. but when I use another-rest-client, It says:
SyntaxError: JSON.parse: unexcepted end of data at line 1 column 1 of the JSON data
but when I click on "edit and resend" and click on "send" without any change on headers, it return correct json in the response section without "SyntaxError: JSON.parse: unexcepted end of data at line 1 column 1 of the JSON data"

I'm using Bottle on Python as backend.

Processing 'multipart/form-data' requests

Yet another problem with this rest client is how to handle 'multipart/form-data' requests (e.g. we want to send post with files).

I was able to make formData, but the header contentType goes without boundary, so the server cannot parse the request.

      rest.conf( {
        contentType: 'multipart/form-data',
        'multipart/form-data': {
          encode: params => {
            return Object.keys( params ).reduce( ( formData, paramName ) => {
              formData.append( paramName, params[ paramName ] )
              return formData
            }, new FormData() )
          }
        }
      } )

      let result = await rest[ UPLOAD ].post( params )

Any idea how to handle it?

Error running simple test

First of all I am not a javascript programmer.

I'm trying to make a simple call to a remote API on one of my servers. The code is below:

<html>
<head>
    <script src="rest-client.js"></script>
    <script>
        window.onload = function () {
            var api = new RestClient('https://api.asscontal.d.datanuvem.com/1.0');
            api.on('request', function(xhr) {
                xhr.setRequestHeader('Authorization', 'someapikey');
            });
            api.res({sites: 'sites'});

            api.sites.get().then(function(k){alert(k)});
        }
    </script>
</head>
<body>
</body>
</html>

However, the browser reports the following errors:

XMLHttpRequest cannot load https://api.asscontal.d.datanuvem.com/1.0/sites. Response for preflight is invalid (redirect)
rest-client.js:167 XHR failed loading: GET "https://api.asscontal.d.datanuvem.com/1.0/sites".
_request @ rest-client.js:167
self.get @ rest-client.js:236
window.onload @ daspanel.html:12
daspanel.html:1 Uncaught (in promise) XMLHttpRequest {readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, onreadystatechange: function…}

The copy of res-client.js I'm using was obtained from this URL: https://raw.githubusercontent.com/Amareis/another-rest-client/master/rest-client.js

What am I doing wrong ?

Thank you.

What is about camelize / decamelize config?

As I can see I cant decamelize request params without own wrapper like

this.api['groups'].post(decamelizeKeys(data)).then(response => {
  return camelizeKeys(response)
})

for each action

RestClient.conf() refactoring

Hi! Very nice little and useful library!
Just as a proposal: why not to use Object.assign() method in your RestClient.conf()?
For example, you can move your default options to the separate file, import it, and then do something like this:

import settings from './settings'
....
conf(options={}) {
  this._opts = Object.assign({}, settings, options)
}

Thanks and good luck!

Generate request with non-unique keys

Hi there and thanks for this library!

Is it possible to create a request with non-unique keys?

In the backend i want to use php-crud-api which has a filter feature which allows multiple filter[] tags to combine conditions where the request would look something like

this.REST.endpoint.get({"filter[]": "name_id,eq," + 1337, "filter[]": "category_id,ge," + 4223, columns: "name, category, timestamp", order: "timestamp, asc" })...

results in the following XHR request:

XHR finished loading: GET "http://localhost/api.php/endpoint?filter%5B%5D=category_id%2Cge%2C4223&columns=name%2C%20category%2C%20timestamp&order=timestamp%2C%20asc"

so the first filter[] part gets truncated.

Simple workaround i found was to explicetly name the indices of the array like

this.REST.endpoint.get({"filter[0]": "name_id,eq," + 1337, "filter[1]": "category_id,ge," + 4223, columns: "name, category, timestamp", order: "timestamp, asc" }).

but i still think itd be great if the library could take care of that or forward the URL unmodified.

Support for blob (or any other) response type

Nice rest client!
But it only works with string response type, because of it's set by default.
So, when we try to work with blob (e.g. trying to get pdf from server), the blob from response goes incorrenct because of wrong xhr.responseType.

To get the pdf get viewed correctly, i had to set responseType manually and handle it in success hook:

    rest
      .on( 'request', xhr => {
        xhr.responseType = 'blob'
      } )
      .on( 'success', xhr => {
        const blob = new Blob( [ xhr.response ], { type: 'application/pdf' } )
        FileSaver.saveAs( blob, `report.pdf` )
      } )
      .on( 'error', xhr => {
      } )
      [ REPORTS ]
      .get( report )

Would be nice to configure the xhr.responseType property and get the results from xhr.reponse, not from xhr.reposneText as it is now.

Rework api for better TypeScript support and overall simplicity

  • Replace custom shortcuts with some inline field which can be inferred by TS (and maybe remove disabling standard shortcuts at all)
    api.res({'some-field: {SHORTCUT: 'someField}}).someField.get()
  • Remove res completely or make it working just like withRes
  • Remove cloning all resources when id is passing - need prev item to be done first
  • Maybe add some possibility to add types for api response (or runtime typechecking with existing libs)
  • Think about #12

Not getting expected headers in XmlHttpRequest during a response

Hello,

I use the following snippet:

    const api = new RestClient("http://localhost:8080/mgag/api");
    api.res("users");
    api.users.post(data).then(function (evt) {
        console.log(evt);
    }, function (other) {
        alert("Unable to subscribe");
        console.log(other);
        console.log(other.getAllResponseHeaders());
    });

Unfortunately, the other parameter doesn't contain any useful headers even if the server sends them.

What I'm getting in Mozzilla Developper Console:
image

image

I want to grab the "Cause" header here.

Please note that I use CORS.

Null response

Firstly i like your library its small and works (i tried jquery.rest but it seems to force parameters on posts), but yours worked straight off, although i do slightly prefer how they support the .post(obj).done(fnDone).fail(fnFail) appraoch rather than .then(fnDone, fnFail) but all in all i still prefer yours.

Now the tiny issue (and fix?):

In WebAPI if you "return Ok()" or StatusCode 204 (no content) it doesnt set a content type, so there is an exception when your library tries to parse the content type ("Cannot read property 'split' of null(…)" on line 140).

This small mod appears to fix it without any unforeseen issues (though you can fix it in anyway you like obviously, since i do not have the time to learn to submit patches just wanted to make the fix as painless as possible).

from
var responseContentType = xhr.getResponseHeader('Content-Type').split(';')[0];
to
var responseContentType = (xhr.getResponseHeader('Content-Type') || "").split(';')[0];

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.