weblocks/app:start
to show the prefix of the app
that is started.(weblocks/debug:on)
and off
so they set the log
level to debug
and warn
, respectively.Fixed processing of the value x-forwarded-port
. Previously, when Weblocks
was used along with lastest (after the 2019-09-07) Woo
server, this header
lead to the 500 error. Because behavior of the Woo
was changed:
https://github.com/fukamachi/woo/issues/84
Now Woo does not parses numberic headers and Weblocks has to do it itself.
A new macro weblocks/routes:defroute
was added.
It defines a handler for a given route. By default route should return a serialized JSON:
(defroute (app /api/data)
"{\"my-data\": [1, 2, 3]}")
but you can redefine the content type:
(defroute (app /api/data :content-type "application/xml")
"<my-data><item>1</item><item>2</item></my-data>")
each route is associate with application class and these routes
are added to the mapper when you call a start
method.
weblocks-websocket
.Unhandled error processing was fixed. There were numerous problems with error processing: * Previosly server stopped to work because clack tried to write into a closed stream. * Also, before this fix, error page didn’t showed propertly. * Any error in the route lead to a server stop because there wasn’t any handler at all.
Now they are handled with
on-error
method as errors in block/page rendering.
All of them are fixed now.
:bordeaux-threads
is in the *features*
, because this does not work
in runtime in precompiled binary.weblocks/session:expire
, which can be used to tell Weblocks to delete current session
after request processing.weblocks/session:get-number-of-sessions
;weblocks/session:get-number-of-anonymous-sessions
;weblocks/widgets/base:get-html-tag
was fixed to
render tables correctly. If the widget’s parent is a :table
element, then this function returns :tr
(instead of a
:div
). If it is :tr
, it returns :td
, and :div
otherwise.weblocks/html:*pretty-html*
was created, to further control pretty printing of html
both in code and in tests.Added a weblocks/response:add-retpath-to
function, useful to add a
retpath
GET parameter to the URL.
For example, calling:
(add-retpath-to "/login" :retpath
"http://example.com:10050/foo/bar")
Will return:
"/login?retpath=http%3A%2F%2Fexample.com%3A10050%2Ffoo%2Fbar"
Argument :retpath
is optional. By default, function
will take an URL of the current web page.
weblocks/utils/i18n
was added to asd file, because
otherwise system weblocks-ui
can’t be installed from the Ultralisp.Previosly, when you called (weblocks/debug:off)
, subsequent
call to (weblocks/debug:status)
returned T
, but should return
NIL
.
This was fixed now.
Request handling pipeline was refactored.
The idea of this refactoring, is to separate roles of the functions
which process requests. Now weblocks/server:handle-http-request
prepares data received from the Clack
and calls
weblocks/request-handler:handle-request
to do the real job.
In it’s turn, weblocks/request-handler:handle-request
should return
an object of type weblocks/response:response
containing a content,
HTTP status code and headers of the response. Any error signal, thrown
from the handle-request
is considered by handle-http-request
as
an “unhandled error” and returned with 500 HTTP status code.
Here is a list of changes:
weblocks/hooks:on-application-hook-handle-request
was
renamed to weblocks/hooks:on-application-hook-handle-http-request
.weblocks/request-handler:handle-client-request
was renamed to weblocks/request-handler:handle-request
and now
this function should return either string
or an object of type
response
. Previously, it also made a non-local exit by throwing a
tag, if request was aborted (for example to return a redirect
response). But now it should only unwind a stack in case if some
unhandled errow was thrown. Any condition of type
weblocks/response:immediate-response
will be catched inside a
:around weblocks/request-handler:handle-request
method and
returned as usual response
object.weblocks/response:abort-processing
was renamed to
weblocks/response:immediate-return
, symbols *code*
,
*headers*
and *content-type
are not exported anymore. Instead
of these global variables, use newly exported functions
get-content
, get-code
, get-headers
, get-custom-headers
and get-content-type
to extract information from the response
object.
* Package weblocks/response
does not export symbols *code*
and
*content-type*
anymore, but exports a function make-response
which can be used by a weblocks/request-handler:handle-reqiest
to
return response.weblocks/request:get-scheme
was added and it is uses
X-Forwarded-Proto
header, if it is available.weblocks/request:get-port
now will use X-Forwarded-Port
header if it is available.weblocks/request:get-host
now will use X-Forwarded-Host
header if it is available.0.33.2
release - system
lack-middleware-session
was loaded successfully, but SBCL was
unable to find lack-middleware-session
package.weblocks/request:get-uri
was fixed to work correctly when
server is behind a reverse proxy which provides X-Forwarded-*
headers.lack-middleware-session
system
because wee use it to store sessions.Now unhandled exceptions are logged with tracebacks if you are using
log4cl-json
library. To turn it on, just do:
(log4cl-json:setup)
Function response:redirect
and it’s JS counterpart was fixed
and now work as expected.
Request processing was streamlined and now
weblocks/server:handle-request
does not contain non-local
exits. This fixes usage of the handle-request
hook, because
previously, if you wrap some code around (call-next-hook)
, then
part following call-next-hook
was ignored.
For example:
(weblocks/hooks:on-application-hook-handle-request
connect-to-database ()
(let ((success nil))
(unwind-protect (progn (setup-transaction)
(weblocks/hooks:call-next-hook)
(setf success t))
(if success
(commit)
(rollback)))))
Before this fix, rollback
always called, because execution never
hitted (setf success t)
. Now this is fixed.
Removed external symbol weblocks/app:make-uri
because it wasn’t
fbound to any function after some refactoring.
Use weblocks/response:make-uri
instead.
widget.lisp
was added to define a
weblocks/widget
package. This solves issues when
ASDF package inferred loading is unable to find weblocks/widget
system. Seems it plays badly when weblocks/widget
is nickname for
weblocks/widgets/base
.start-weblocks
. It is called around the
code in (weblocks/server:start)
and can be used to setup some
additional routes, for example.Previosly, there was an error if you are using ASDF’s package inferred
system class and don’t have explicit dependency on the weblocks
page.
The error was raised during code loading:
;;; > Error: There is no applicable method for the generic function:
> #<STANDARD-GENERIC-FUNCTION WEBLOCKS/JS/BASE:MAKE-JS-BACKEND #x3020027E292F>
> when called with arguments:
> (:JQUERY)
Now it is fixed and package weblocks/js/jquery
is a dependency of
weblocks/server
and always loads.
package-inferred-system
class.We don’t enforce *print-pretty*
inside of
weblocks/html:with-html
macro. This hack was required because
the bug in the spinneret, which was fixed at 2018-01-04:
https://github.com/ruricolist/spinneret/commit/06b280612aff07cf376f593746d080230f2c7462
Error was fixed when you are trying to start a server which is already running. Now you have a “restart” to stop the old version of the server before starting the new one.
However, it does not work with Woo
server, because C library libev
crashes with error:
Assertion failed: (("libev: a signal must not be attached to two different loops", !signals [w->signum - 1].loop || signals [w->signum - 1].loop == loop)), function ev_signal_start, file ev.c, line 4082
Class weblocks/dependencies:dependency
now requires that type
attribute shoulde be of type (member :css :js :png :jpg :gif)
Also, functions make-local-js-dependency
,
make-local-css-dependency
, make-local-image-dependency
,
make-remote-js-dependency
and make-remote-css-dependency
were
removed from package weblocks/dependencies
. Use make-dependency
function, it will figure out which dependency type to create itself.
A new function weblocks/debug:get-session-value
was added. It can be
used to get values from the last session seen by weblocks.
Error handling was fixed. Previously it aborted Woo’s worker thread and break the server.
Variable weblocks/variables::*catch-errors-p*
was renamed to
weblocks/variables::*invoke-debugger-on-error*
and it’s value was
inverted. If this variable is True, then debugger will be
invoked. Otherwise - Weblocks will return 500 error page.
Argument :invoke-debugger-on-errors
of weblocks/debug:on
function was renamed to :invoke-debugger-on-error
.
Method weblocks/error-handler:on-error
now is called when you abort
request processing from the debugger. It is called with current app as
the first argument and the nil
instead of condition.
Fixed a typo in string-widget
and funcall-widget
package definitions.
Now string-widget
and funcall-widget
depends on
weblocks/widgets/base
instead of ``weblocks/widget.
Reloading of the defapp definition now does not tries to restart an application. Previously, restart caused the problem – when there is only one application, whole Weblocks server was shut down. So, I’ve removed this implicit action.
Code which logs action result on the client-side was improved.
Symbols add-application-hook
, add-request-hook
,
add-session-hook
, prepare-hooks
and call-hook
aren’t exported from weblocks/hooks
anymore. Use new macro
defhook
instead.
Here is how it works:
You use defhook
as the toplevel form of your file if you want to define
a new hook. This macro will create few other macroses in
weblocks/hooks
package and will export them. For example:
(defhook database-opened
"This hook is called when your application opens a database.")
This code will add these macroses into the weblocks/hooks
package:
on-session-hook-database-opened
,
on-request-hook-database-opened
,
on-application-hook-database-opened
,
with-database-opened-hook
and
call-database-opened-hook
.
You need to wrap code, which opens a database, with
with-database-opened-hook
:
(weblocks/hooks:with-database-opened-hook ()
(do-some-staff-to-open-database))
And in any other piece of code, you can define callbacks, using one of other three macroses:
(weblocks/hooks:on-session-hook-database-opened
log-database-opening ()
(weblocks/hooks:call-next-hook)
(log:info "Database was opened"))
Usage of defhook
macro gives more transparency to all defined hooks,
because all of them now visible as external symbols in
weblocks/hooks
package.
System weblocks/hooks
now depends on log4cl
and
metatilities
, because previously sometimes it was impossible to load weblocks
.
Old tests for widgets, removed from core framework were removed.
Tests for widget’s MOP methods were ported to Rove.
Package weblocks/utils/close
now loaded with main :weblocks
system.
Few old widget tests were removed.
Added function weblocks/session:reset
which resets current session.
Quickstart tutorial was fixed!
Function make-js-action
was moved to weblocks/actions
package.
Package weblocks/app
now exports functions stop
and restart
.
Previously they were internal and were called like stop-webapp
and
restart-webapp
.
Package weblocks/server
does not export start-weblocks
and
stop-weblocks
functions. They were replaced with just start
and
stop
. Also, it’s internal generics start
and stop
were
renamed and transformed to start-server
and stop-server
functions.
File default-application.lisp
was removed, because now every
application has default session initialization method.
File default-init.lisp
was refactored. Now it provides default
method for weblocks/session:init
generic and :around
method for
same generic, which allows end user just to return a string or a
function from his init
method.
Now user can return any string or function from his method
weblocks/session:init
and it will be passed to a new generic
weblocks/widget:create-widget-from
to create a root widget. You can
also define create-widget-from
for you custom types.
Function weblocks/debug:on
now turns on mode when Weblocks does not
intercept unhandled conditions, but calls an interactive debugger.
session-name-string-pair
this function was removed in previous
releases, but didn’t find it’s way to the changelog, still used in
some older tests not ported to the Rove.defrender
was removed.All rendering code was refactored.
Macroses with-html
and with-html-to-string
replaced
with weblocks.html:with-html
and weblocks.html:with-html-string
.
Stream *weblocks-output-stream*
was moved to
weblocks.html::*stream*
and is not external anymore. Please, don’t
use it directly.
Procedure update-widget-tree
was removed and not widgets can’t
change html header’s tags, description, title, etc. If you need this,
change them in the render
method.
Macro root-widget
was removed and replaced with function
weblocks.widgets.root:get
.
Functions post-action-redirect
, post-render-redirect
and
initial-request-p
were removed from weblocks
package.
Function pure-request-p
was moved to weblocks.request
package.
Variable *json-content-type*
was removed.
Variable *latest-request*
was moved to
weblocks.debug:*latest-request*
.
Functions parse-location-hash
, ajax-request-p
were moved to
weblocks.request
package.
Function redirect
was moved to weblocks.response:redirect
.
Functionality, related to opening another window instead of redirection
or deferring redirection until the end of action or rendering was
removed.
Functions remove-duplicate-dirty-widgets
,
update-location-hash-dependents
and update-widget-tree
were
removed.
Call to weblocks::update-dialog-on-request
from
handle-client-request
was commented.
Generic method weblocks/error-handler:on-error
now accepts two
arguments - application object and condition.
All code from uri-parameters-slotmap.lisp
was removed.
All code, related to application class, was moved to the package
weblocks.app
. Base aplication class was renamed to
weblocks.app:app
, and macro for definition of the new
application was renamed to weblocks.app:defapp
.
All code related to application’s metaclass, was moved to
the package weblocks.app-mop
. Metaclass was renamed to
weblocks.app-mop:app-class
.
Application’s slot html-indent-p
and corresponding accessor
weblocks-webapp-html-indent-p
were removed because now spinneret
generates non indented code.
Slot init-user-session
was completely removed and replace with a generic
weblocks.session:init
.
These dependency related slots and accessors were removed:
application-dependencies
weblocks-webapp-application-dependencies
bundle-dependency-types
version-dependency-types
gzip-dependency-types
And macro for defining a special readers for them was removed as well:
def-debug-p-slot-readers
.
Also, these arguments to defapp
was removed:
:ignore-default-dependencies
, :dependencies
Function update-thread-status
and method webapp-update-thread-status
were removed.
Function get-webapps-for-class
was renamed to app-active-p
and
now returns t
if application of given class is already active.
Function start-webapp
was renamed to weblocks.app:start
.
Function get-webapp
was renamed to get-active-app
and optional
argument error-p
was renamed to keyword argument signal-error
.
Function find-app
was removed.
Function in-webapp
was moved to weblocks.debug:in-app
.
Variable *default-webapp*
was removed.
Variable *active-webapps*
was renamed to
weblocks.app::*active-apps*
and made internal. Use
weblocks.app:get-active-apps
function.
Reader weblocks-webapp-prefix
was renamed to
weblocks.app:get-prefix
.
Slot default-store-name
and its accessor
webapp-default-store-name
were removed.
Variable *current-webapp*
was moved to
weblocks.variables::*current-app*
.
Functions compute-webapp-public-files-uri-prefix
,
compute-webapp-public-files-uri-prefix
,
compute-webapp-public-files-path
,
make-webapp-public-file-uri
,
weblocks-webapp-public-files-cache-time
and variable
*default-public-files-path*
were removed because
now there is another way to serve static.
Function webapp-serves-hostname
was renamed to
weblocks.app:app-serves-hostname-p
and now accepts app as the first
argument and hostname as the second.
Variable *uri-tokens*
was removed and weblocks does not set
‘last-request-uri session value to all uri tokens anymore.
Macro with-webapp
was moved to weblocks.app:with-app
.
Function webapp-permanent-action
was moved to
weblocks.app-actions:get-action
.
Function add-webapp-permanent-action
was moved to
weblocks.app-actions:add-action
and remove-webapp-permanent-action
to
weblocks.app-actions:remove-action
.
Macroses define-permanent-action
and define-permanent-action/cc
were moved to weblocks.app-actions:define-action
and
weblocks.app-actions:define-action/cc
.
Function make-webapp-uri
was removed, use
weblocks/response:make-uri
instedad.
Accessor webapp-js-backend
was renamed to get-js-backend
These functions were moved into the separate package
weblocks.current-app
and renamed:
webapp-prefix
-> get-prefix
;Function weblocks.actions:add-command
was moved to
weblocks.commands
.
Function weblocks:get-request-action
was moved to
weblocks/actions:get-request-action
Keyword argment :action
was removed from action calls.
Package weblocks.js
was renamed to weblocks/js/base
.
Functions escape-script-tags
, %js
and macroses
with-javascript
, with-javascript-to-string
were moved to the
package weblocks/js/base
.
These variables were moved from weblocks
package to
weblocks/variables
:
*current-page-title*
*current-page-keywords*
*current-page-headers*
*rewrite-for-session-urls*
*default-content-type*
*ignore-missing-actions*
dom-object-mixin
dom-id
request-uri-path
add-get-param-to-url
remove-parameter-from-uri
pluralize
singularize
proper-number-form
vowelp
consonantp
proper-indefinite-article
articlize
*current-locale*
current-locale
russian-proper-number-form
noun-vocative-to-genitive
*debug-words-forms*
*debug-words-genders*
determine-gender
style-warn
webapp-style-warning
renamed to style-warning
.non-idempotent-rendering
misunderstood-action
function-or-action->action
make-action
generate-action-code
To make Weblocks core smaller, many files were removed: views
, widgets
,
html-parts
, utilities
.
Systems weblocks-util
, weblocks-testutils
were removed.
Accessor dom-class
and generic function dom-classes
were removed
and replaced with generic function weblocks/widget:get-css-classes
.
Generic function weblocks:handle-error-condition
was removed.
Variable *dirty-widgets*
was removed along with
render-dirty-widgets
function.
Rendering of remote (non cached) dependencies was fixed.
weblocks.routes:*routes*
is not external anymore.
Use weblocks.routes:add-route
and weblocks.routes:get-route
to add new routes and to search a route matched on a path.weblocks.widget:update
method when making :update-widget
or :insert-widget (before)
commands.weblocks::child-of-p
for new type of
widget. This should fix some issues, with widgets updating.weblocks.widget:widget
was exported, to make possible to
define widgets based on it and some mixins.Most functions from weblocks.request
were refactored and renamed:
request-parameters
-> get-parameters
;request-parameter
-> get-parameter
;request-header
-> get-header
;remove-request-header
-> remove-header
;request-server-name
-> get-host
;request-server-port
-> get-port
;request-uri
-> get-uri
(and now it returns full URI with
scheme, host and port;request-path-info
-> get-path
(and now it has keyword argument
with-params
to copy behaviour of old request-uri
and return
strings like /some/path?with=parameters
;request-method
-> get-method
.All these function now accept keyword argument :request
. Previously
it was &optional
.
Another change is a new function weblocks.response:make-uri
. It can
be used to build new uri, based on the uri of the current request. This
can be useful when embedding links into emails, for example.
Warning
These changes require a newer version of Lack.
I’ve made a pull request https://github.com/fukamachi/lack/pull/31 it is not merged yet, so, alternative version of Lack can be used, by installing it using Qlot, from here:
weblocks.session:get-value
was replaced with a regular
function.weblocks.session:set-value
was removed and replaced with
a setter (setf get-value)
.Package weblocks.debug
now does not export *on
variable,
but provides three functions on
, off
and status
.
New method weblocks.server:serve-static-file
was introduced.
It can be used to create static routes which will respond with
file’s content. For example, you could add this to your app’s
initialize-instance
method:
(weblocks.server:serve-static-file
"/favicon.png"
(asdf:system-relative-pathname :app "favicon.png"))
*random-state*
to itself for each request to
allow it to use setf
and change *random-state*
until the end
of request processing.*expired-action-handler*
, method
expired-action-handler
and function
default-expired-action-handler
were replaced with method
weblocks.actions:on-missing-action
.weblocks:handle-client-request ((app weblocks-webapp))
was removed. Look at it’s newer version in weblocks.request-handler
.Commented out call to update-widget-tree
inside of (setf
widget-children)
, because it breaks on
(get-widgets-by-type 'selector :root obj)
sometimes. Seems this is
because I’ve removed selector’s code previously.
Warning
Probably parent/children handling code will be removed soon.
Backtrace printing code was replaced with direct usage of
trivial-backtrace:print-backtrace
.
Call to prepare-hooks
was moved from weblocks.request-handler:handle-client-request
to the the weblocks.server:handler-request, to fix session hooks processing when
:process-request
hook is called.
(weblocks.error-handler:on-error app)
call.weblocks.actions
package.commands
were introduced. Commands describe remote calls
which have to be applied on a client as a result of action’s
execution. Previously, weblocks used similar technic to replace dirty
widgets and to execute some javascript code before or after
replacement. The new mechanism of “commands” is more generic and uses
the JSON-RPC to pass function name and parameters from backend to
client-side.weblocks.session:in-session-p
function which returns t
if session data can be retrived or stored without error.initiateActionWithArgsAndCallback
send arguments as
JSON payload. This allows to send any datastructures as action’s params.weblocks.response:send-script
was changed to use new
mechanizm with commands. When you send script from the action, it will
add a command :execute-code
to the stack. All commands are
executed in same order as they were added. If you want some code to be
executed before widget update, just execute send-code
before
weblocks.widget:update
.New package was introduced - weblocks.widget
it contains a new
widget
class with simplified rendering based on spinneret
templating library.
Now class route
is exported from weblocks.routes
and should be
used instead of routes:route
.
New package weblocks.error-handler
was introduced. It contains a
on-error
generic method which is called when some unhandled error
raise by application.
Fixed issue of adding multuple routes mapped to the same path. Now if url mapper already have a route all subsequent attempts to add a route with same path are ignored.
Fixed error:
Undefined function WEBLOCKS:WEBAPP-SESSION-KEY called with arguments
(#<APP::APP #x3020052F01DD>)
Fixed Content-Type
of the default 500 page. Previously it was
plain/text
and browser didn’t undestand that and downloaded the
file.
Now Content-Type
is text/plain
.
Now weblocks does not checks if all tokens from URL were consumed by app during root widget rendering. Previously it returned 404 if some token weren’t consumed. Implement this logic in your app if needed.
Macro assert-hooks-called
was changed to return hooks in the order
they were called. Also, now it waits hooks description as a DSL,
like:
(assert-hooks-called
(:fact-created contact "vasya@pupkin.com")
(:fact-removed contact "vasya@pupkin.com"))
New system weblocks-testutils
was introduced. It
compiles weblocks.t.utils
package which macroses useful for
unittesting.
Also, a new macro catch-hooks
was added to check if some
hooks were called during a unittest.
Now weblocks does not open a new tab or window on 500 error during an action execution.
declaim optimize
in different places. These
declarations changed compiler’s settings at unexpected moments.with-hook
macro returns the value of the last form’s evaluation.render-page
was fixed to really wrap
page with <html>...
block.weblocks.request:remove-request-header
now
returns a new instance of request object and does not modify the
original request. This fixes issue in weblocks-websocket
.weblocks.debug
and keeping latest
session was rewritten using :process-request
hook.weblocks.request:remove-request-header
.(:reset-session session)
, which is
called around a code for clearing given session. Right now it is
called only from weblocks.sessions:reset-latest-session
.html
, menu
, suggest
and repl
utilities
were excluded.
Code which was in request-handler.lisp
, was excluded
from build and partly moved to request-handler2.lisp
.
Added :stop-weblocks
hook.
Misc helper for repl were removed: sessions
,
in-session
and pt
. May be the will be restored in separate
package.
Page boilerplate rendering method render-page
now
does not use complex templating with contextes.
Symbols refactoring:
* *style-warn-on-circular-dirtying*
variable ->
weblocks.variables
;
*style-warn-on-late-propagation*
variable ->
weblocks.variables
;gen-id
function -> weblocks.session
;send-script
function -> weblocks.response
;with-html-form
macro -> weblocks-ui
;*approved-return-codes*
variable -> weblocks.variables
;handle-ajax-request
method -> weblocks.request-handler
;update-location-hash-dependents
function ->
weblocks.request-handler
.render-link
function was moved to weblocks-ui.form
in
separate system.weblocks.hooks:call-hook
helper.call-next-hook
is called automatically if it
wasn’t called explicitly.Package weblocks.request-hooks
was renamed to weblocks.hooks
.
Macro with-dynamic-hooks
was renamed to with-hook
.
Functions add-application-hook, add-session-hook, add-request-hook became a macroses and their argument lists were changed. Now the should be used like:
(weblocks.hooks:add-session-hook
:some-hook
my-beautiful-callback (param)
(do-something-useful-with param))
weblocks.request-hooks:eval-hooks
was renamed to
weblocks.hooks:call
and now can be called with params:
(weblocks.hooks:call :some-hook
first-param
second-param)
Added :handle-request
dynamic hook called around request handling code.
Called when weblocks.request:*request*
and weblocks.session:*session*
are already bound.
get-cross-origin
and :cross-origin
were removed to
get-crossorigin
and :crossorigin
, to conform the html
attibute’s spelling.(weblocks:redirect...)
call.ajax-progress
is present, it will be shown
and hidden by jQuery’s .show
and .hide
methods. Also, they
take optional speed parameters from data-*
attributes
data-show-speed
and data-hide-speed
.