Comments (33)
rust-mustache is pretty decent.
I'm not sure about making this middleware. Do mean create a new piece of middleware that acts as the templating engine?
I'm familiar with how Express does this for NodeJs. The developer configures Express to pass through res.render() invocations to the templating engine. The developer also supplies template director(y|ies). Do you plan to create something similar?
from iron.
This is tricky, because we'd like the method to be implemented on Response
but access some form of app-global configuration - you'd set up the templating by adding a Middleware with some options on it like the templating engine and template directories, but I'm not sure how that information gets to res.render.
This are good thoughts to be having, but I'm not sure what the answer is.
from iron.
I just realized that Mixins would make Middleware an ideal way to provide a replaceable templating engine. Sorry I'm a little slow on the uptake.
Perhaps, we could establish a convention that a particular Alloy entry (maybe something like a Vec of Path objects) contains the directories for whatever template engine Middleware is used. There could be a Hashmap in Alloy for per-engine app-wide configuration settings.
A third part of the convention could be that a piece of middleware acting as the render engine would provide a res.render() method via Mixins.
How does that strike your fancy?
from iron.
I think it's cleaner to just provide a Templating
trait that any template engine could implement, then you provide an instance of that trait to the templating middleware and it uses that for res.render
. My main concern is that res.render
would have no access to the Alloy
and therefore no access to any configuration.
This is solvable by placing a second Alloy
in Response, but I'm not sure if that's the way to go. I think there is a better, more general way to do app-wide configuration than this, but I'm not sure how yet.
Maybe the best way would be to add a global-configuration Alloy on each Iron instance - then provide a &-reference to the app in both request and response? This is fast but also quite convenient, and could in fact be made memory efficient by storing the global Alloy behind an Arc, so it is not cloned for each request.
from iron.
Yes! That's essentially what express does with app.set(key, value)
and app.get(key)
. Is no other way to provide config, other than in fn arguments?
It seems like there may be other app-wide configuration needs that may come along anyway -- there should a simple app-wide in memory data-store ready to go.
from iron.
I'm only concerned that adding a reference to the app in Request
and Response
makes testing trickier - right now I've managed to create a small mocking library for Request
and Response
that does not have to resort to unsafe anywhere (https://github.com/reem/iron-test) but an app reference may make that trickier.
from iron.
Ugh -- that would suck. Hmmm, maybe we could check for an environmental variable (IRON_VIEWS) and fallback to a default directory for templates (./views). I'm not sure if I'm in love with this idea, but it should prevent any unsafe could or references back to Iron in res or req...
I saw that repo. I'm super excited to play with that.
from iron.
There's way too much of std::mem::unitialized
in our tests right now, so that would be great to fix.
I'd really rather not fall back to an environment variable. Maybe, instead of a global persistent reference to Iron, we could just have a global persistent reference to some sort of global preferences object that only coincidentally happens to be stored on Iron
.
I think that we'll find, however, that there may be a need for a general-purpose Alloy-like structure on Response.
from iron.
Yeah, relying only on environment variables is wrong.
from iron.
I think there needs to be a dedicated way to immutably access shared global configuration. More thoughts to come.
from iron.
I think the solution is to include a config: Arc<AnyMap>
in both Request and Response. This allows easy global configuration and is pretty easy to mock in tests.
from iron.
I think this is the most ergonomic solution. Would it make any difference if the config is accessed in Response or Request? It feels wrong to provide the same information in two places, but I can't think of any particular problems with this idea.
from iron.
I think providing access to config in both places is perfectly fine.
from iron.
The configuration problem is mostly solved through the Read
variant in Persistent
and the interface it exposes.
from iron.
I don't know if this question is relevant, just curious if it's possible to compile a view as part of the build process. For example there is play! framework for Scala, where views are normal scala files, statically checked and compiled by the scala compiler (https://playframework.com/documentation/2.3.x/ScalaTemplates). I wonder if it's possible to do the same in Rust.
from iron.
You can definitely do this with a syntax extension, or even without one if you are willing to lose a bit of expressiveness. However, I think that's probably the domain of a templating engine, not this middleware.
from iron.
it could be interesting to look at the way Nickel has implemented mustache support
from iron.
@aochagavia They have done much of the work that we'd like to do, but I'd much rather be templating engine agnostic and support a richer interface - notably nickels .render
only allows HashMap<&'static str, &'static str>
which means that you can't render a template with dynamic data, like from a database.
from iron.
as someone was noting for scala, in cppcms , a webframework in C++ (so in the same segment of "compiled language") the use template file , that get compiles into C++
basically the idea is that your template file is converted into a C++ class + a name , which is then added to a hashmap, then in your "controller" methods you just do
render(content_structure, "name_of_the_template")
content_structure being a plain struct, with the data you want to render in your template.
The advantage I see to this approach is
- possibility to add dynamic data
- compile time check, (the same as people of the posgresql rust library have created a compile time check of the SQL statement)
- performance (as it's only compiled once)
- still possible for corner case to inject "raw" rust code
If that seems interesting, I can provide more details on how it is implemented as I've been working with this templating system quite extensively (and would interested to re implement it in Iron)
http://cppcms.com/wikipp/en/page/cppcms_1x_templates_gen
http://cppcms.com/wikipp/en/page/cppcms_1x_templates_comm
from iron.
@allan-simon sounds like this would really put us ahead of the node / ruby / python community by really leveraging all the best parts of rustc.
from iron.
Agreed. There could be some really cool work to be done in making a crazy syntax extensions for creating templates.
from iron.
I've finished a side project of mine these last days, and I've started today to take a look at syntax extensions, I will soon create a "toy" repository on my github to keep track on my progress on comprehension of "how to create complex syntax extensions" , so that at the end I could use to have a tutorial on how the machinery work, so that we donβt end up with an unmaintainable extension.
I will keep you updated on my progress for this, though I think it's going to take me at least a week or two before getting a "beginning of proof of concept", but things will get faster after a good grasp on this.
from iron.
@allan-simon I also just recently started learning about syntax extensions. If you want an example of a (hopefully) well written one: https://github.com/reem/stainless
from iron.
@reem Perfect it will help a lot.
from iron.
Hello, just to keeps you updated, using your stainless extension and brain_fuck macro, I've started a toy html template extension and now i'm able to generate function to output html and to mix rust code in it
https://bpaste.net/show/62c46adedcb2
right now I have 2 tags
- <% template name() %> which generate a function "name() -> String"
- <% rust xxxxxx %> that permits to "inject" rust code inside a template, I've first implemented this one because it was IMHO the most complex one (the others will follow the same logic as <% template %>, and it will permit to have "workarounds" waiting for me to implement more specific tags (like <% if %> etc.
other things are treated as html and added to the output buffer returned by string
Right now I'm still making myself clear about what i want, and I will tell you when I got something that reflect my idea of the templating engine I want, so that we can start discussing about making change on it
from iron.
@allan-simon I think it would probably be best to adopt an existing templating standard and possibly just make changes to it, rather than starting from scratch.
The most ideal situation is that I can create static
or const
templates which are aware of the types they must be passed to be rendered, then I can get nice type errors if I try to pass incompatible things as the pieces of the template.
from iron.
actually as said, I'm basing the syntax/concept fully on the one of the "cppcms" framework, (which I think was also based on an existing one, as vim was able to put a nice syntaxic coloration) as I think it's closer to what I'm doing (i.e template transformed into native code at compilation time)
and yup as you said, the goal is to have the same garanty in the template as we have in rust, i.e if it compiles then you're sure it works (i.e syntax checking / type checking etc.)
from iron.
Hi, I have talked with @reem in IRC but also want to update here. I have been working on a handlebars template engine for rust and I'm going to create an iron middleware for integration.
By far, the handlebars-rust project is almost finished and should support most of handlebars features, helper customization and template inheritance. I'm now working on the middleware. Since it's still difficult to compile iron against rust nightly, I may still need several days for it.
As discussed with @reem, we will create a new Template
struct contains template name and data you want to render. Template
will implement Modifier
for Response
, so users can call response.set(template)
. The information will be stored in extensions and processed by middleware. I'm also going to keep it easy to test. So users can test their handlers by retrieving data from extensions (in test function).
from iron.
To answer some questions above, handlebars is a widely used template syntax created by Yokuda Hatz (yes, it's who made cargo also) originally in javascript. In handlebars-rust, there is a tricky point that you have to make the data implements ToJson
so we can render it. Because in handlebars, there's if/else, each and some other custom flow controls, data are not only for rendering, but also to control rendering. So I can't just use a "Show" trait or String/&str type for it. Lucky enough, most common data structure implements ToJson
, so we can use it without (too much) pain.
from iron.
Just a note, but its Yehuda Katz, aka wycats. :)
from iron.
Oh, sorry for wycats.
from iron.
The middleware handlebars-iron is done and available from crates.io
from iron.
I think this can be closed since handlebars-iron seems to work fairly well.
from iron.
Related Issues (20)
- replace WriteBody with Into<Body>
- about "too many open file" HOT 4
- URL Parser Unable to Handle IPv6 Addresses HOT 1
- unable to build on nightly (2019-08-01) HOT 1
- Unable to build on nightly HOT 3
- iron::params not parsing query string parameters in 0.6.1 UrlEncodedQuery seems to work with same example. HOT 1
- Typo in documentation link (modifiers) HOT 2
- Keywords and categories in Cargo.toml
- question: Is this repo still in active development? HOT 3
- Unix Domain?
- Is iron Async/Await supported? HOT 1
- Iron::https uses Protocol::http on v0.6.1
- ironframework.io not resolving HOT 3
- ironframework.io serves malicious content HOT 5
- Tests error with latest Rust 1.49
- Is this project still maintained? HOT 2
- Add stale-while-revalidate to CacheDirective
- stop|restart an Iron server
- `req.url` stripping fragments? HOT 2
- Should this crate be used anymore ? HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from iron.