dojo / core

:rocket: Dojo 2 - language helpers and utilities.
http://dojo.io
Other
213 stars 62 forks source link

Not an issue, question about request and querystrings #167

Open sebilasse opened 8 years ago

sebilasse commented 8 years ago

Hey, currently writing an "auth" module using core/request and wonder if the parsing of querystrings could go to the request module as a responseType because I think it is common (?) :

import { UrlSearchParams } from '../../core/src/main';

/**
 * Add a filter that automatically parses incoming querystrings.
 */
filterRegistry.register(
    function (response: Response<any>, url: string, options: RequestOptions) {
        return typeof response.data && options && options.responseType === 'querystring';
    },
    function (response: Response<any>, url: string, options: RequestOptions): Object {
        return {
                data: (new Parameters(String(response.data))).get()
            };
    }
);
sebilasse commented 8 years ago

What I find confusing in general is the current inconsistency between ES and node.js' URL module: E.g. currently the naming is searchParams in ES 'URL' and query in node.js 'url' …

A feature request for UrlSearchParams: dojo output { a: [ 'b' ], b: [ '1' ], doC: [ '' ] } node output { a: 'b', b: '1', doC: '' }

I agree but it would be fine to have the node output interpretation as well ...

sebilasse commented 8 years ago

@kitsonk fyi … I am currently using this "polyfill" and I thought it would be fair to post it here :

import { has } from '../../core/src/main';
import { UrlSearchParams } from '../../core/src/main';
const url = (has('host-node')) ? require('url') : window.URL;

export class Parameters extends UrlSearchParams {
  constructor(input?: any) {
    super(input);
  }
  /**
     * Returns a plain object with all first values OR
   * the first value associated with a key here!
     * @param key The key to return the first value for
     * @return The first string value for the key
     */

  get(key?: string): any {
    if (!this.has(key)) {
      return Object.keys(this._list).reduce((_o,key,i,arr): any => {
        _o[key] = this._list[key][0];
        return _o;
      }, {});
    }
    return this._list[key][0];
  }
}
class URL {
  static protocolPattern = /^([a-z0-9.+-]+:)/i;
  static hostlessProtocol = {
  'javascript': true,
  'javascript:': true
  };
  // protocols that always contain a // bit.
  static slashedProtocol = {
    'http': true,
    'https': true,
    'ftp': true,
    'gopher': true,
    'file': true,
    'http:': true,
    'https:': true,
    'ftp:': true,
    'gopher:': true,
    'file:': true
  }
  static format(urlObject: any|string) {
    if (has('host-node')) {
      return url.format(urlObject);
    };
    return (new url(urlObject)).toString();
  }
  static parse(urlStr: string, parseQuery: boolean = false, slashesDenoteHost: boolean = false) {
    if (has('host-node')) {
      return url.parse(urlStr, parseQuery, slashesDenoteHost);
    }
    const U = new url(urlStr);
    U.path = [U.pathname||'', U.search||''].join('');
    // auth
    const pw = (typeof U.password === 'string' && U.password.length) ?
      [':',U.password].join('') : '';
    U.auth = (typeof U.username === 'string' && U.username.length) ?
      [U.username,U.password] : '';
    // query
    if (parseQuery) {
      U.query = (typeof U.searchParams === 'object' ) ?
        U.searchParams : new Parameters(U.search||'').get();
    } else {
      U.query = U.search;
    }
    // slashes
    var rest = urlStr;
    rest = rest.trim();
    var proto: RegExpExecArray = URL.protocolPattern.exec(rest);
    if (proto) {
      var lowerProto = proto[0].toLowerCase();
      U.protocol = lowerProto;
      rest = rest.substr(proto[0].length);
    }
    if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
      var slashes = (rest.substr(0, 2) === '//');
      var lowerProto = proto[0].toLowerCase();
      if (slashes && !(lowerProto && URL.hostlessProtocol[lowerProto])) {
        rest = rest.substr(2);
        U.slashes = true;
      }
    }
    return U;
  }
  static resolve(from: string, to: string) {
    if (has('host-node')) {
      return url.resolve(from, to);
    };
    /* TODO FIXME and implement browser */
  }
}
export default URL;