Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show an error message when an error response does not have JSON #157

Merged
merged 4 commits into from
Aug 14, 2015
Merged
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
12 changes: 11 additions & 1 deletion extensions/chrome/js/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,21 @@ function initPanelMessage() {
function initReqRes() {
chrome.runtime.onMessage.addListener(handleMessage);

function extractProps(xhr) {
var props = {};
for (var key in xhr) {
if (typeof xhr[key] === 'string' || typeof xhr[key] === 'number') {
props[key] = xhr[key];
}
}
return props;
}

function handleMessage(req, sender, sendResponse) {
if (req.type === 'request') {
var url = tabInfo[req.tabId].remoteHost + '/' + req.url;
REPLConsole.request(req.method, url, req.params, function(xhr) {
sendResponse({ status: xhr.status, responseText: xhr.responseText });
sendResponse(extractProps(xhr));
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is to use xhr.statusText.

});
}
return true;
Expand Down
1 change: 1 addition & 0 deletions lib/web_console.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
require 'web_console/whitelist'
require 'web_console/request'
require 'web_console/response'
require 'web_console/view'

module WebConsole
mattr_accessor :logger
Expand Down
15 changes: 15 additions & 0 deletions lib/web_console/locales/en.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
en:
errors:
unavailable_session: |
Session %{id} is is no longer available in memory.

If you happen to run on a multi-process server (like Unicorn or Puma) the process
this request hit doesn't store %{id} in memory. Consider turning the number of
processes/workers to one (1) or using a different server in development.

unacceptable_request: |
A supported version is expected in the Accept header.

connection_refused: |
Oops! Failed to connect to the Web Console middleware.
Please make sure a rails development server is running.
14 changes: 2 additions & 12 deletions lib/web_console/middleware.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,6 @@ module WebConsole
class Middleware
TEMPLATES_PATH = File.expand_path('../templates', __FILE__)

UNAVAILABLE_SESSION_MESSAGE = <<-END.strip_heredoc
Session %{id} is is no longer available in memory.

If you happen to run on a multi-process server (like Unicorn or Puma) the process
this request hit doesn't store %{id} in memory. Consider turning the number of
processes/workers to one (1) or using a different server in development.
END

UNACCEPTABLE_REQUEST_MESSAGE = "A supported version is expected in the Accept header."

cattr_accessor :mount_point
@@mount_point = '/__web_console'

Expand Down Expand Up @@ -115,13 +105,13 @@ def change_stack_trace(id, request)

def respond_with_unavailable_session(id)
json_response(status: 404) do
{ output: format(UNAVAILABLE_SESSION_MESSAGE, id: id)}
{ output: format(I18n.t('errors.unavailable_session'), id: id)}
end
end

def respond_with_unacceptable_request
json_response(status: 406) do
{ error: UNACCEPTABLE_REQUEST_MESSAGE }
{ output: I18n.t('errors.unacceptable_request') }
end
end
end
Expand Down
4 changes: 4 additions & 0 deletions lib/web_console/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,9 @@ class Railtie < ::Rails::Railtie
Middleware.whiny_requests = config.web_console.whiny_requests
end
end

initializer 'i18n.load_path' do
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly that, yes! 👍

config.i18n.load_path.concat(Dir[File.expand_path('../locales/*.yml', __FILE__)])
end
end
end
31 changes: 2 additions & 29 deletions lib/web_console/template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,6 @@ module WebConsole
# It introduces template helpers to ease the inclusion of scripts only on
# Rails error pages.
class Template
class Context < ActionView::Base
# Execute a block only on error pages.
#
# The error pages are special, because they are the only pages that
# currently require multiple bindings. We get those from exceptions.
def only_on_error_page(*args)
yield if @env['web_console.exception'].present?
end

# Render JavaScript inside a script tag and a closure.
#
# This one lets write JavaScript that will automatically get wrapped in a
# script tag and enclosed in a closure, so you don't have to worry for
# leaking globals, unless you explicitly want to.
def render_javascript(template)
render(template: template, layout: 'layouts/javascript')
end

# Render inlined string to be used inside of JavaScript code.
#
# The inlined string is returned as an actual JavaScript string. You
# don't need to wrap the result yourself.
def render_inlined_string(template)
render(template: template, layout: 'layouts/inlined_string')
end
end

# Lets you customize the default templates folder location.
cattr_accessor :template_paths
@@template_paths = [ File.expand_path('../templates', __FILE__) ]
Expand All @@ -43,8 +16,8 @@ def initialize(env, session)

# Render a template (inferred from +template_paths+) as a plain string.
def render(template)
context = Context.new(template_paths, instance_values)
context.render(template: template, layout: false)
view = View.new(template_paths, instance_values)
view.render(template: template, layout: false)
end
end
end
24 changes: 22 additions & 2 deletions lib/web_console/templates/console.js.erb
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,33 @@ REPLConsole.prototype.commandHandle = function(line, callback) {
return status >= 200 && status < 300 || status === 304;
}

function parseJSON(text) {
try {
return JSON.parse(text);
} catch (e) {
return null;
}
}

function getErrorText(xhr) {
if (!xhr.status) {
return "<%= t 'errors.connection_refused' %>";
} else {
return xhr.status + ' ' + xhr.statusText;
}
}

putRequest(self.getUrl(), params, function(xhr) {
var response = JSON.parse(xhr.responseText);
var response = parseJSON(xhr.responseText);
var result = isSuccess(xhr.status);
if (result) {
self.writeOutput(response.output);
} else {
self.writeError(response.output);
if (response && response.output) {
self.writeError(response.output);
} else {
self.writeError(getErrorText(xhr));
}
}
callback(result, response);
});
Expand Down
16 changes: 3 additions & 13 deletions lib/web_console/testing/fake_middleware.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
require 'action_view'
require 'action_dispatch'
require 'active_support/core_ext/string/access'
require 'json'
require 'web_console/whitelist'
require 'web_console/request'
require 'web_console/view'

module WebConsole
module Testing
Expand All @@ -20,7 +22,7 @@ def call(env)
end

def view
@view ||= create_view
@view ||= View.new(@view_path)
end

private
Expand All @@ -33,18 +35,6 @@ def req_path(env)
def render(template)
view.render(template: template, layout: nil)
end

def create_view
lookup_context = ActionView::LookupContext.new(@view_path)
lookup_context.cache = false
FakeView.new(lookup_context)
end

class FakeView < ActionView::Base
def render_inlined_string(template)
render(template: template, layout: "layouts/inlined_string")
end
end
end
end
end
33 changes: 33 additions & 0 deletions lib/web_console/view.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module WebConsole
class View < ActionView::Base
# Execute a block only on error pages.
#
# The error pages are special, because they are the only pages that
# currently require multiple bindings. We get those from exceptions.
def only_on_error_page(*args)
yield if @env['web_console.exception'].present?
end

# Render JavaScript inside a script tag and a closure.
#
# This one lets write JavaScript that will automatically get wrapped in a
# script tag and enclosed in a closure, so you don't have to worry for
# leaking globals, unless you explicitly want to.
def render_javascript(template)
render(template: template, layout: 'layouts/javascript')
end

# Render inlined string to be used inside of JavaScript code.
#
# The inlined string is returned as an actual JavaScript string. You
# don't need to wrap the result yourself.
def render_inlined_string(template)
render(template: template, layout: 'layouts/inlined_string')
end

# Escaped alias for "ActionView::Helpers::TranslationHelper.t".
def t(key, options = {})
super.gsub("\n", "\\n")
end
end
end
6 changes: 6 additions & 0 deletions test/templates/config.ru
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,9 @@ map "/mock/repl/error" do
body = [ { output: 'fake-error-message' }.to_json ]
run lambda { |env| [ 400, headers, body ] }
end

map "/mock/repl_sessions/error.txt" do
headers = { 'Content-Type' => 'plain/text' }
body = [ 'error message' ]
run lambda { |env| [ 400, headers, body ] }
end
15 changes: 15 additions & 0 deletions test/templates/spec/repl_console_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,21 @@ describe("REPLConsole", function() {
assert.ok(hasClass(this.message, 'error-message'));
});
});

context("remotePath: /mock/repl_sessions/error.txt", function() {
beforeEach(function(done) {
var self = this;
var options = { remotePath: '/mock/repl_sessions/error.txt' };
self.console = REPLConsole.installInto('console', options);
self.console.commandHandle('fake-input', function(result, response) {
self.message = self.elm.getElementsByClassName('console-message')[0];
done();
});
});
it("should output HTTP status code", function() {
assert.match(this.message.innerHTML, /400 Bad Request/);
});
});
});

describe(".installInto()", function() {
Expand Down