Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ The schemes you can use include haxelib, github, gitlab, and http/https:

Note that for github and gitlab you can specify credentials using the `--gh-credentials` and `--gl-private-token` parameters respectively. Be warned though that these credentials are then baked into the hxmls as well. Be very careful about using this option.

Note: authentication via .netrc file is supported! If present, a .netrc / ~.netrc will be used for URLs that require authentication.
See [the curl .netrc documentation](https://everything.curl.dev/usingcurl/netrc.html) for more information.

Because **haxelib** is a prominent source for stable versions, a **shortcut** is available: `lix +lib <libname>`. e.g. `lix +lib hxcpp#3.4.188` is equivalent for `lix install haxelib:hxcpp#3.4.188`.

### Removing a dependency
Expand Down
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"devDependencies": {
"@vercel/ncc": "^0.38.1",
"graceful-fs": "^4.1.15",
"netrc": "^0.1.4",
"tar": "^6.0.1",
"yauzl": "github:lix-pm/yauzl"
},
Expand Down
71 changes: 71 additions & 0 deletions src/lix/client/Auth.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package lix.client;

import js.node.Buffer;
import js.node.Url;

/**
* Authentication is opt-in - if no credentials are found, downloads proceed without auth.
* currently only auth via .netrc is available
*/
class Auth {

static public function getHostname(url:String):Null<String> {
try {
var parsed = Url.parse(url);
return parsed.hostname;
} catch (e:Dynamic) {
return null;
}
}

static public function getNetrcAuth(hostname:String):Null<{login:String, password:String}> {
if (hostname == null) return null;

try {
var netrc = js.Lib.require('netrc');
var credentials = netrc();
var machine = Reflect.field(credentials, hostname);

if (machine != null) {
var login = Reflect.field(machine, 'login');
var password = Reflect.field(machine, 'password');

if (login != null && password != null) {
return {
login: login,
password: password
};
}
}
} catch (e:Dynamic) {
// .netrc not found, parse error, or netrc package not installed
}

return null;
}

static public function hasNetrcAuth(hostname:String):Bool {
return getNetrcAuth(hostname) != null;
}

static public function createBasicAuthHeader(login:String, password:String):String {
var auth = '$login:$password';
var encoded = Buffer.from(auth).toString('base64');
return 'Basic $encoded';
}

static public function getAuthHeaders(url:String):Dynamic {
var headers = {};

var hostname = getHostname(url);
if (hostname == null) return headers;

var netrcAuth = getNetrcAuth(hostname);
if (netrcAuth != null) {
Reflect.setField(headers, 'authorization',
createBasicAuthHeader(netrcAuth.login, netrcAuth.password));
}

return headers;
}
}
7 changes: 7 additions & 0 deletions src/lix/client/Download.hx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package lix.client;

import haxe.Timer;
import lix.client.uncompress.*;
import lix.client.Auth;
import js.node.Buffer;
import js.node.Url;
import js.node.Http;
Expand Down Expand Up @@ -289,6 +290,12 @@ class Download {
options.headers = {};
options.headers['user-agent'] = Download.USER_AGENT;

// Add authentication headers from .netrc if available
var authHeaders = Auth.getAuthHeaders(url);
for (key in Reflect.fields(authHeaders)) {
Reflect.setField(options.headers, key, Reflect.field(authHeaders, key));
}

function fail(e:js.Error)
cb(Failure(tink.core.Error.withData('Failed to download $url because ${e.message}', e)));

Expand Down