Giter Site home page Giter Site logo

metal-uri's Introduction

metal-uri

Build Status

Build Status

Class for parsing and formatting URIs.

Use

After passing a URI as a string to the constructor, the individual components of the URI can be accessed and updated with the provided setters and getters.

Simple use case

import Uri from 'metal-uri';

const uri = new Uri('http://foo:8080');

uri.getHostname(); // 'foo'
uri.getPort(); // '8080'
uri.getProtocol(); // 'http:'

Updating values

const uri = new Uri('http://foo:8080/path');

uri.setPathname('login');
uri.setProtocol('https:');
uri.setHostname('bar');
uri.setPort('81');

uri.toString(); // 'https://bar:81/login'

Handling query parameters

const uri = new Uri('http://hostname?a=1&b=2');

uri.getParameterValue('a'); // '1'
uri.getParameterValue('b'); // '2'

uri.removeParameter('a');
uri.setParameterValue('b', 'x');
uri.addParameterValue('c', 'y');

uri.toString(); // 'http://hostname/?b=x&c=y'
uri.getSearch(); // '?b=x&c=y'

You can also set multiple values for one parameter.

const uri = new Uri('http://hostname?a=1');

uri.addParameterValues('b', ['x', 'y']);

uri.toString(); // 'http://hostname/?a=1&b=x&b=y'

Non-standard protocols

A default protocol is added automatically when none is provided. This default value will either be http: or https: depending if you are on a secure connection or not.

In order to use other protocols, you must instruct Uri to not add a default protocol by passing false as the second argument.

const uri = new Uri('tel:555-555-5555', false);

uri.setPathname('1-555-555-5555');

uri.toString(); // tel:/1-555-555-5555

Setup

  1. Install a recent release of NodeJS if you don't have it yet.

  2. Install local dependencies:

npm install
  1. Run the tests:
npm test

Contributing

Check out the contributing guidelines for more information.

metal-uri's People

Contributors

eduardolundgren avatar ipeychev avatar jbalsas avatar mairatma avatar vbence86 avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

metal-uri's Issues

Unit test for parseFromAnchor function is dodgy

Declaimer

This module has been linked to Travis CI in travis branch (https://github.com/metal/metal-uri/tree/travis), but the test apparently fails against certain Saucelabs browsers.

Travis Output

https://travis-ci.org/metal/metal-uri/builds/258612453

Recurring issues
  • parseFromAnchor should throw a TypeError exception on invalid URLs FAILED
  • parse should throw a TypeError exception on invalid URLs FAILED

While looking into this issue we came across that the function responsable for URL validation is a bit dodgy and fails in its purpose. It creates an <a> instance and sets its href attribute against the given URL that is believed to be invalid. The specified browsers taking part in the test nevertheless automatically generate a valid URL out of this invalid one by invoking a transparent native code as soon as the <a> instance's href attribute is altered.

Proposal

Please double check whether or not the existence of this test provides any value to the building process.

The dodgy code snippet copied from parseFromAnchor.js

	var link = document.createElement('a');
	link.href = opt_uri;

	if(link.protocol === ':' || !/:/.test(link.href)) {
		throw new TypeError(`${opt_uri} is not a valid URL`);
	}

Fallback doesn't not throw errors when expected

Hey, guys. I would like to bring here a discussion I had with @brunobasto.

The fallback used in Metal URI doesn't behave as expected. Differently of the main implementation, the fallback doesn't throw errors.

One example of this is when the url port exceeds the maximum allowed 65535:

For the given url http://localhost:99999 the following happens:

  • The main implementation throws Failed to construct 'URL': Invalid URL.
  • The fallback doesn't throw errors and we don't have a consistency behaviour in how browsers interpret this. Safari 5 for example replaces the given port 99999 by the maximum number allowed 65535, others replace by 0.

There is a pull request for SennaJS to prevent crashes because of errors from Metal URI, but the test fails in browsers that use the fallback.

Throws an exception in ReactNative 16

In ReactNative 16 this check fails since URL is an object, but URL.length is 0.

Question: What if we drop the current implementation which uses URL or parsing via a element and replace it with a specially prepared module for that purpose, which has small footprint and does not use any native objects? This could be url-parse module.

Add information if protocol was added to the original Uri

Currently after uri.toString() the Uri is always returned with protocol (scheme), but there is no way for the user to know if the scheme was added by the Uri implementation, or it was already present in the original Uri.
Let's add a new property and function to return this information.

Add support for ReactNative environment

We need the project to run in ReactNative environment. The project currently uses NodeJS libraries to parse the URL if browser is not available which fails in ReactNative.

Problems consuming [email protected]

Moving our parse logic to url-parse has the side-effect of a less-than-ideal necessary build step or setup.

Someone consuming it needs to be aware of how to build it. There might be several scenarios:

Webpack / Rollup / Browserify build

This is expected to work as the bundling tools already know how to deal with the different dependencies

Karma config setup

Currently, a very barebone setup for testing modules consuming metal-* dependencies looked like this:

  frameworks: ['mocha', 'chai', 'sinon', 'source-map-support', 'commonjs'],

  files: [
    'node_modules/metal/src/**/*.js',
    'node_modules/metal-*/src/**/*.js',
    'src/**/!(node)/*.js',
    'test/environment/browser/env.js',
    'test/**/*.js',
  ],

  exclude: ['src/env/node.js', 'test/**/node/**/*.js'],

  preprocessors: {
    'src/**/*.js': ['babel', 'commonjs'],
    'node_modules/metal/**/*.js': ['babel', 'commonjs'],
    'node_modules/metal-*/**/*.js': ['babel', 'commonjs'],
    'test/**/*.js': ['babel', 'commonjs'],
  },

  babelPreprocessor: {options: babelOptions},

A project depending on metal-uri would now likely need to add browserify and serve additional files such as node_modules/url-parse (and transitive dependencies) or serve and preprocess everything inside node_modules just to be sure.

While I guess we would all agree this is not the ideal scenario, what options do we have? Should we:

  • Ship a browser-compatible version of metal-uri to be consumed directly in the browser
  • Clarify the setup configuration steps
  • Move the parse implementation back into the module

@eduardolundgren, @ipeychev, @Robert-Frampton, thoughts?

JS error will occur when using the URI constructor with a protocol handler like tel or mailto

The maybeAddProtocolAndHostname_(opt_uri) method prepends the uri with http:// and then passes the value to the parse method which is trying to create a new URL(opt_uri) with the original protocol and the http//: protocol prepending it.

For example, if href="tel:123-123-1234" it will try to create a new URL(opt_uri) where opt_uri = "http://tel:123-123-1234".

This will cause the following JS error to occur:
Uncaught TypeError: Failed to construct 'URL': Invalid URL

As of now, I know that this is an issue for the following protocol handlers:

  • tel
  • mailto
  • skype

I ran into this issue while trying to utilize an anchor to navigate to an application via sennaJS.

Trailing slash being removed

When passing a string like /path/ this component is removing the trailing slash to /path.

new metal.Uri('/path/').toString() === '/path'

This can cause errors when using Senna depending on how Apache/Nginx is configured to handle URL redirects.

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.