Skip to content

Commit

Permalink
Release 1.3.0
Browse files Browse the repository at this point in the history
Fix multiple regressions introduced in 1.2.0
Consolidated download endpoints (fixes #58)(fixes #51)
Added Content-Length header (thanks oleksandr-torosh)
  • Loading branch information
ArekSredzki committed Jul 28, 2016
1 parent 1c56c04 commit 7192c42
Show file tree
Hide file tree
Showing 14 changed files with 79 additions and 88 deletions.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@ If you host your project on your Github **and** do not need a UI for your app, t
- Use pretty much any database for persistence, thanks to [Sails](http://sailsjs.org) & [Waterline](http://waterlinejs.org)
- :sparkles: Simple but powerful download urls (**NOTE:** when no assets are uploaded, server returns `404` by default):
- `/download/latest`
- `/download/latest/:os`
- `/download/:version`
- `/download/:version/:os`
- `/download/channel/:channel`
- `/download/channel/:channel/:os`
- `/download/latest/:platform`
- `/download/:version
- `/download/:version/:platform
- `/download/:version/:platform/:filename
- `/download/channel/:channel
- `/download/channel/:channel/:platform
- :sparkles: Support pre-release channels (`beta`, `alpha`, ...)
- :sparkles: Auto-updates with [Squirrel](https://github.com/Squirrel):
- Update URLs provided: `/update/:platform/:version[/:channel]`
- Mac uses `*.dmg` and `*.zip`
- Windows uses `*.exe` and `*.nuget`
- Windows uses `*.exe` and `*.nupkg`
- :sparkles: Serve the perfect type of assets: `.zip` for Squirrel.Mac, `.nupkg` for Squirrel.Windows, `.dmg` for Mac users, ...
- :sparkles: Release notes endpoint
- `/notes/:version`
Expand Down
7 changes: 3 additions & 4 deletions api/controllers/AssetController.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,9 @@ module.exports = {
* This is because Squirrel.Windows does a poor job of parsing the filename,
* and so we must fake the filenames of x32 and x64 versions to be the same.
*
* (GET /download/channel/:channel/:platform?)
* (GET /download/version/:version/:platform?)
* (GET /download/:platform/:version/:filename)
* (GET /download/:platform?)
* (GET /download/latest/:platform?': 'AssetController.download')
* (GET /download/:version/:platform?/:filename?': 'AssetController.download')
* (GET /download/channel/:channel/:platform?': 'AssetController.download')
*/
download: function(req, res) {
var channel = req.params.channel;
Expand Down
8 changes: 4 additions & 4 deletions api/controllers/VersionController.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,8 @@ module.exports = {
return res.ok({
url: url.resolve(
sails.config.appUrl,
'/download/version/' + latestVersion.name +
'/' + latestVersion.assets[0].platform + '?filetype=zip'
'/download/' + latestVersion.name + '/' +
latestVersion.assets[0].platform + '?filetype=zip'
),
name: latestVersion.name,
notes: releaseNotes,
Expand Down Expand Up @@ -237,8 +237,8 @@ module.exports = {
assets = _.map(latestVersion.assets, function(asset) {
asset.name = url.resolve(
sails.config.appUrl,
'/download/' + asset.platform + '/' + latestVersion.name + '/' +
latestVersion.channel + '/' + asset.name
'/download/' + latestVersion.name + '/' + asset.platform + '/' +
asset.name
);

return asset;
Expand Down
47 changes: 27 additions & 20 deletions api/services/AssetService.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
*/

var mime = require('mime');
var path = require('path');

var fsx = require('fs-extra');
var crypto = require('crypto');
var Promise = require('bluebird');
Expand All @@ -14,21 +16,24 @@ var SkipperDisk = require('skipper-disk');
var AssetService = {};

AssetService.serveFile = function(req, res, asset) {
var fileAdapter = SkipperDisk();
// Sent file properties in header
res.setHeader('Content-Disposition', 'attachment; filename="' + asset.name + '"');
res.setHeader('Content-Length', asset.size);
res.setHeader('Content-Type', mime.lookup(asset.fd));

// Stream the file to the user
var fileStream = fileAdapter.read(asset.fd)
var fileStream = fsx.createReadStream(asset.fd)
.on('error', function(err) {
sails.log.error('An error occurred while accessing update asset.', err);
res.serverError('An error occurred while accessing update asset.');
res.serverError('An error occurred while accessing asset.', err);
sails.log.error('Unable to access asset:', asset.fd);
})
.on('open', function() {
// Send file properties in header
res.setHeader(
'Content-Disposition', 'attachment; filename="' + asset.name + '"'
);
res.setHeader('Content-Length', asset.size);
res.setHeader('Content-Type', mime.lookup(asset.fd));
})
.on('end', function complete() {
// After we have sent the file, log analytics, failures experienced at this
// point should only be handled internally (do not use the res object).
// After we have sent the file, log analytics, failures experienced at
// this point should only be handled internally (do not use the res
// object).
//
// Atomically increment the download count for analytics purposes
//
Expand All @@ -38,18 +43,22 @@ AssetService.serveFile = function(req, res, asset) {
'UPDATE asset SET download_count = download_count + 1 WHERE name = \'' + asset.name + '\';',
function(err) {
if (err) {
sails.log.error('An error occurred while logging asset download', err);
sails.log.error(
'An error occurred while logging asset download', err
);
}
});
} else {
asset.download_count++;

Asset.update( {
name: asset.name
}, asset)
.exec(function (err) {
Asset.update({
name: asset.name
}, asset)
.exec(function(err) {
if (err) {
sails.log.error('An error occurred while logging asset download', err);
sails.log.error(
'An error occurred while logging asset download', err
);
}
});
}
Expand All @@ -66,12 +75,10 @@ AssetService.serveFile = function(req, res, asset) {
AssetService.getHash = function(fd) {
return new Promise(function(resolve, reject) {

var fileAdapter = SkipperDisk();

var hash = crypto.createHash('sha1');
hash.setEncoding('hex');

var fileStream = fileAdapter.read(fd)
var fileStream = fsx.createReadStream(asset.fd)
.on('error', function(err) {
reject(err);
})
Expand Down
2 changes: 1 addition & 1 deletion assets/js/download/download-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ angular.module('app.releases', [])
}

self.downloadUrl = '/download/' + (asset.version || versionName) +
'/' + asset.name;
'/' + asset.platform + '/' + asset.name;
};

$scope.$on('$destroy', function() {
Expand Down
19 changes: 8 additions & 11 deletions bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
"name": "electron-release-server",
"private": true,
"dependencies": {
"angular": "^1.5.7",
"bootstrap-sass-official": "^3.3.6",
"angular-animate": "^1.5.7",
"angular-messages": "^1.5.7",
"angular-route": "^1.5.7",
"angular-sanitize": "^1.5.7",
"angular": "^1.5.8",
"bootstrap-sass-official": "^3.3.7",
"angular-animate": "^1.5.8",
"angular-messages": "^1.5.8",
"angular-route": "^1.5.8",
"angular-sanitize": "^1.5.8",
"angular-xeditable": "~0.2.0",
"lodash": "~4.13.1",
"lodash": "~4.14.0",
"angular-ui-notification": "~0.2.0",
"angular-bootstrap": "~1.3.3",
"angular-confirm-modal": "^1.2.5",
Expand All @@ -24,9 +24,6 @@
"ng-device-detector": "^3.0.1",
"compare-versions": "^2.0.2"
},
"devDependencies": {
"angular-mocks": "^1.5.7"
},
"appPath": "app",
"overrides": {
"angular-xeditable": {
Expand All @@ -41,6 +38,6 @@
}
},
"resolutions": {
"angular": "^1.5.7"
"angular": "^1.5.8"
}
}
5 changes: 2 additions & 3 deletions config/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,9 @@ module.exports.routes = {
view: 'homepage'
},

'GET /download/latest/:platform?': 'AssetController.download',
'GET /download/:version/:platform?/:filename?': 'AssetController.download',
'GET /download/channel/:channel/:platform?': 'AssetController.download',
'GET /download/version/:version/:platform?': 'AssetController.download',
'GET /download/:platform/:version/:filename': 'AssetController.download',
'GET /download/:platform?': 'AssetController.download',

'GET /update': 'VersionController.redirect',
'GET /update/:platform/:version': 'VersionController.general',
Expand Down
5 changes: 3 additions & 2 deletions docs/update-windows.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ http://download.myapp.com/update/win64/:version/:channel/RELEASES
```
If the channel is not specified, then `stable` will be used. If `win64` is used but only a `win32` asset is available, it will be used.

Your application just need to configure `Update.exe` or `Squirrel.Windows` to use `http://download.myapp.com/update/win32/:version/:channel` as a feed url (:warning: without query parameters).
> Note: If desired, you can use `windows_32` instead of `win32` and `windows_64` instead of `win64`.
Your application just need to configure `Update.exe` or `Squirrel.Windows` to use `http://download.myapp.com/update/win32/:version/:channel` as a feed url (:warning: without query parameters).

You'll just need to upload as release assets: `*-delta.nupkg` and `-full.nupkg` (files generated by `electron-builder` or `Squirrel.Windows` releaser).
You'll just need to upload as release assets: `-full.nupkg` (files generated by `electron-builder` or `Squirrel.Windows` releaser).

The RELEASES file will be generated for you :)
8 changes: 6 additions & 2 deletions docs/urls.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@
Electron Release Server provides a variety of urls to access release assets.

#### Latest version for detected platform:
`http://download.myapp.com/download/latest` or `http://download.myapp.com/download`
`http://download.myapp.com/download/latest`
#### Latest version for specific platform:
`http://download.myapp.com/download/latest/osx` or `http://download.myapp.com/download/osx`
`http://download.myapp.com/download/latest/osx`
#### Specific version for detected platform:
`http://download.myapp.com/download/1.1.0`
#### Specific version for a specific platform:
`http://download.myapp.com/download/1.2.0/osx`
#### Specific file for a version for a specific platform:
_Note that only the file extension is used._

`http://download.myapp.com/download/1.2.0/windows_64/MyApp-0.1.1-full.nupkg`
#### Specific channel:
`http://download.myapp.com/download/channel/beta`
#### Specific channel for specific platform:
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "electron-release-server",
"private": true,
"version": "1.2.1",
"version": "1.3.0",
"description": "A version server for hosting and serving the your electron desktop app releases.",
"dependencies": {
"bluebird": "^3.4.1",
Expand All @@ -26,7 +26,7 @@
"include-all": "~0.1.6",
"jsonwebtoken": "^7.1.6",
"ldapauth-fork": "^2.5.2",
"lodash": "^4.13.1",
"lodash": "^4.14.0",
"mime": "^1.3.4",
"passport": "^0.3.2",
"passport-ldapauth": "^0.5.0",
Expand Down
2 changes: 1 addition & 1 deletion views/403.pug
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ html
.container-fluid
.navbar-header
a.pull-left(href='/')
img.navbar-logo(src='images/logo.svg')
img.navbar-logo(src='/images/logo.svg')
a.navbar-brand(href='/') Electron App
.collapse.navbar-collapse
ul.nav.navbar-nav
Expand Down
28 changes: 6 additions & 22 deletions views/404.pug
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
doctype html
html
head
title Unexpected Error Occurred
title Page not found

// STYLES
link(rel="stylesheet", href="/min/production.min.css")
Expand All @@ -12,7 +12,7 @@ html
.container-fluid
.navbar-header
a.pull-left(href='/')
img.navbar-logo(src='images/logo.svg')
img.navbar-logo(src='/images/logo.svg')
a.navbar-brand(href='/') Electron App
.collapse.navbar-collapse
ul.nav.navbar-nav
Expand All @@ -24,24 +24,8 @@ html
.jumbotron
h1
span.glyphicon.glyphicon-fire.red
| 500
| 404
p.lead
| The web server is returning an internal error
| .
a.btn.btn-default.btn-lg.text-center(href='javascript:document.location.reload(true);')
span.green Try This Page Again
.container
.body-content
.row
.col-md-6
h2 What happened?
p.lead
| A 500 error status implies there is a problem with the web server's software causing it to malfunction.
.col-md-6
h2 What can I do?
p.lead If you're a site vistor
p
| Nothing you can do at the moment. If you need immediate assistance, please send us an email instead. We apologize for any inconvenience.
p.lead If you're the site owner
p
| This error can only be fixed by server admins, please contact your website provider.
| The requested page is not available.
a.btn.btn-default.btn-lg.text-center(href='/')
span.green Go Home
7 changes: 3 additions & 4 deletions views/500.pug
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ html
.container-fluid
.navbar-header
a.pull-left(href='/')
img.navbar-logo(src='images/logo.svg')
img.navbar-logo(src='/images/logo.svg')
a.navbar-brand(href='/') Electron App
.collapse.navbar-collapse
ul.nav.navbar-nav
Expand All @@ -24,10 +24,9 @@ html
.jumbotron
h1
span.glyphicon.glyphicon-fire.red
| 500
| 500
p.lead
| The web server is returning an internal error
| .
| The web server is returning an internal error.
a.btn.btn-default.btn-lg.text-center(href='javascript:document.location.reload(true);')
span.green Try This Page Again
.container
Expand Down
12 changes: 6 additions & 6 deletions views/homepage.pug
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ html
meta(name='author', content='Arek Sredzki')
meta(name='viewport', content='width=device-width, initial-scale=1')
base(href="/")

// bower:css
link(rel='stylesheet', href='/bower_components/angular-ui-notification/dist/angular-ui-notification.css')
link(rel='stylesheet', href='/bower_components/components-font-awesome/css/font-awesome.css')
// endbower
// STYLES
link(rel="stylesheet", href="/min/production.min.css")
// STYLES END
Expand All @@ -22,7 +22,7 @@ html
.container-fluid
.navbar-header
a.pull-left(href='/')
img.navbar-logo(src='images/logo.svg')
img.navbar-logo(src='/images/logo.svg')
a.navbar-brand(href='/') Electron App
.collapse.navbar-collapse
ul.nav.navbar-nav
Expand All @@ -37,11 +37,11 @@ html
.footer
p
i.fa.fa-fw.fa-code
| with
| with
i.fa.fa-fw.fa-heart
| by Arek Sredzki


// bower:js
script(src='/bower_components/angular/angular.js')
script(src='/bower_components/jquery/dist/jquery.js')
Expand Down

0 comments on commit 7192c42

Please sign in to comment.