From 8a43e4ebb1dee678b0c84e3d7e38d11ad8af823d Mon Sep 17 00:00:00 2001 From: jocelyn Date: Thu, 14 Jun 2012 05:50:27 -0700 Subject: [PATCH 01/13] Updated Home (markdown) --- Home.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Home.md b/Home.md index 59860185..54238b40 100644 --- a/Home.md +++ b/Home.md @@ -4,7 +4,8 @@ The official documentation/wiki is located at https://github.com/EiffelWebFramew - Mailing list: please visit and subscribe to the mailing list page [[http://groups.google.com/group/eiffel-web-framework]] ![logo](http://groups.google.com/intl/en/images/logos/groups_logo_sm.gif) -- Most of the discussion are done on the mailing list (google group). For time to time we have web meeting, and physical meeting usually during other Eiffel related events. +- Most of the topics are discussed on the mailing list (google group). +- For time to time we have web meeting, and less frequently physical meetings that occurs usually during other Eiffel related events. - See also - You want to contribute or follow the progress/discussion, see the [[collaboration page| Community-collaboration]] From 51e54311b1b7a00b6a97125930f3373997080cc6 Mon Sep 17 00:00:00 2001 From: colin-adams Date: Thu, 14 Jun 2012 22:13:02 -0700 Subject: [PATCH 02/13] Updated Task json (markdown) --- Task-json.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Task-json.md b/Task-json.md index e8c22725..f4ccd3fe 100644 --- a/Task-json.md +++ b/Task-json.md @@ -7,4 +7,4 @@ - and then let Eiffel Software include it, in the official libraries ## Roadmap ## -- this should be done before 1st of October \ No newline at end of file +- this should be done before 1st of October - so has this been achieved? \ No newline at end of file From e2adc3cfbbcf98c9d3242aeb5847446bd8c01411 Mon Sep 17 00:00:00 2001 From: colin-adams Date: Thu, 14 Jun 2012 22:13:52 -0700 Subject: [PATCH 03/13] Updated Tasks Roadmap (markdown) --- Tasks-Roadmap.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Tasks-Roadmap.md b/Tasks-Roadmap.md index 69ba8900..e4aece3c 100644 --- a/Tasks-Roadmap.md +++ b/Tasks-Roadmap.md @@ -31,4 +31,6 @@ ## Contributors ## - See [[the collaboration page|Community-collaboration]] -note: In bold, you see the responsible for each task, but contribution from other is possible as well. \ No newline at end of file +note: In bold, you see the responsible for each task, but contribution from other is possible as well. + +This needs updating, I think. \ No newline at end of file From bd5985a99acfb94ca8837e888d4d201d1607034a Mon Sep 17 00:00:00 2001 From: colin-adams Date: Fri, 15 Jun 2012 07:10:36 -0700 Subject: [PATCH 04/13] Created Library conneg (markdown) --- Library-conneg.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 Library-conneg.md diff --git a/Library-conneg.md b/Library-conneg.md new file mode 100644 index 00000000..0a901256 --- /dev/null +++ b/Library-conneg.md @@ -0,0 +1 @@ +Testing \ No newline at end of file From d0e9438d46bc4486ca69f2973787895fca03a090 Mon Sep 17 00:00:00 2001 From: colin-adams Date: Fri, 15 Jun 2012 07:44:14 -0700 Subject: [PATCH 05/13] Updated Library conneg (markdown) --- Library-conneg.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Library-conneg.md b/Library-conneg.md index 0a901256..7362b58a 100644 --- a/Library-conneg.md +++ b/Library-conneg.md @@ -1 +1,13 @@ -Testing \ No newline at end of file +# Server-driven content negotiation + +EWF supports server-driven content content negotiation, as defined in [HTTP/1.1 Content Negotiation](http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html#sec12.1) . To enable this facility: + +1. Add ${EWF}/library/network/protocol/conneg/conneg.ecf to your system ECF. +1. In the class where your handlers reside, add an attribute `conneg: CONNEG_SERVER_SIDE`, and ensure it is always attached (create in the creation procedure, or make it a once, or add an attribute body). An example creation call is: `create conneg.make ({HTTP_MIME_TYPES}.application_json, "en", "UTF-8", "")`. + +That call defines our defaults for media-type, language, charset and encoding, respectively. The encoding could also be written as `"identity"`. It means no compression. As an alternative, we might code `"gzip"`. + +The user agent (a web browser, for example. or the curl program), can request different representations by using headers. For example, `Accept: application/json; q=0.2, application/xml` says the client would be very happy to get back an XML representation (if you omit the q for quality parameter, it defaults to 1, which is best), but (s)he will tolerate JSON. Clearly, we are going to be able to satisfy that client, as we serve JSON by default. But what if the client had requested `Accept: application/xml;q=0.8, text/html`? In this example, we are going to serve both JSON and XML representations upon request. A client who requests `Accept: text/html, text/plain` is going to be disappointed. For the other aspects (language, charset and encoding), we are not going to offer any choices. That does not mean we ignore the client's headers for these aspects. We are going to check if our representation is acceptable to the client, and if not, return a 406 Not Acceptable response (an alternative is to send our representation anyway, and let the user decide whether or not to use it). + + + From 74079325a09f89f2651fdd6d45e54b017397ab99 Mon Sep 17 00:00:00 2001 From: colin-adams Date: Fri, 15 Jun 2012 07:57:48 -0700 Subject: [PATCH 06/13] Updated Library conneg (markdown) --- Library-conneg.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/Library-conneg.md b/Library-conneg.md index 7362b58a..2d43309e 100644 --- a/Library-conneg.md +++ b/Library-conneg.md @@ -9,5 +9,51 @@ That call defines our defaults for media-type, language, charset and encoding, r The user agent (a web browser, for example. or the curl program), can request different representations by using headers. For example, `Accept: application/json; q=0.2, application/xml` says the client would be very happy to get back an XML representation (if you omit the q for quality parameter, it defaults to 1, which is best), but (s)he will tolerate JSON. Clearly, we are going to be able to satisfy that client, as we serve JSON by default. But what if the client had requested `Accept: application/xml;q=0.8, text/html`? In this example, we are going to serve both JSON and XML representations upon request. A client who requests `Accept: text/html, text/plain` is going to be disappointed. For the other aspects (language, charset and encoding), we are not going to offer any choices. That does not mean we ignore the client's headers for these aspects. We are going to check if our representation is acceptable to the client, and if not, return a 406 Not Acceptable response (an alternative is to send our representation anyway, and let the user decide whether or not to use it). +Next, we need to declare all the representations we support: + +` mime_types_supported: LINKED_LIST [STRING] is + -- Media types `Current' supports + once + create Result.make + Result.put_front ({HTTP_MIME_TYPES}.application_xml) + Result.put_front ({HTTP_MIME_TYPES}.application_json) + ensure + mime_types_supported_not_void: Result /= Void + no_void_entry: not Result.has (Void) + end + + charsets_supported: LINKED_LIST [STRING] is + -- Character sets `Current' supports + once + create Result.make + Result.put_front ("UTF-8") + ensure + charsets_supported_not_void: Result /= Void + no_void_entry: not Result.has (Void) + end + + encodings_supported: LINKED_LIST [STRING] is + -- Encodings `Current' supports + once + create Result.make + Result.put_front ("identity") + Result.put_front ("") -- identity encoding + ensure + encoding_supported_not_void: Result /= Void + no_void_entry: not Result.has (Void) + end + + languages_supported: LINKED_LIST [STRING] is + -- Languages `Current' supports + once + create Result.make + Result.put_front ("en") + ensure + languages_supported_not_void: Result /= Void + no_void_entry: not Result.has (Void) + end + +Now we are in a position to do some negotiating. At the beginning of your handler(s), code: + From 53a206694a5bdd7d583be773375239f576f254f3 Mon Sep 17 00:00:00 2001 From: colin-adams Date: Fri, 15 Jun 2012 08:04:30 -0700 Subject: [PATCH 07/13] Updated Library conneg (markdown) --- Library-conneg.md | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/Library-conneg.md b/Library-conneg.md index 2d43309e..9aa4ed8b 100644 --- a/Library-conneg.md +++ b/Library-conneg.md @@ -12,7 +12,7 @@ The user agent (a web browser, for example. or the curl program), can request di Next, we need to declare all the representations we support: ` mime_types_supported: LINKED_LIST [STRING] is - -- Media types `Current' supports + -- Media types 'Current' supports once create Result.make Result.put_front ({HTTP_MIME_TYPES}.application_xml) @@ -23,7 +23,7 @@ Next, we need to declare all the representations we support: end charsets_supported: LINKED_LIST [STRING] is - -- Character sets `Current' supports + -- Character sets 'Current' supports once create Result.make Result.put_front ("UTF-8") @@ -33,7 +33,7 @@ Next, we need to declare all the representations we support: end encodings_supported: LINKED_LIST [STRING] is - -- Encodings `Current' supports + -- Encodings 'Current' supports once create Result.make Result.put_front ("identity") @@ -44,7 +44,7 @@ Next, we need to declare all the representations we support: end languages_supported: LINKED_LIST [STRING] is - -- Languages `Current' supports + -- Languages 'Current' supports once create Result.make Result.put_front ("en") @@ -55,5 +55,20 @@ Next, we need to declare all the representations we support: Now we are in a position to do some negotiating. At the beginning of your handler(s), code: - +` +local + l_media_variants: MEDIA_TYPE_VARIANT_RESULTS + do + l_media_variants:= conneg.media_type_preference (mime_types_supported, a_req.http_accept) + if not l_media_variants.is_acceptable then + send_unacceptable_media_type (a_res) + elseif not conneg.charset_preference (charsets_supported, a_req.http_accept_charset).is_acceptable then + send_unacceptable_charset (a_res) + elseif not conneg.encoding_preference (encodings_supported, a_req.http_accept_encoding).is_acceptable then + send_unacceptable_encoding (a_res) + elseif not conneg.language_preference (languages_supported, a_req.http_accept_language).is_acceptable then + send_unacceptable_encoding (a_res) + else + -- We have agreed a representation, let's go and serve it to the client +` From c9b11a6401c61b5ab8537183070b85970d48af77 Mon Sep 17 00:00:00 2001 From: colin-adams Date: Fri, 15 Jun 2012 08:09:39 -0700 Subject: [PATCH 08/13] Updated Library conneg (markdown) --- Library-conneg.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Library-conneg.md b/Library-conneg.md index 9aa4ed8b..4bf63725 100644 --- a/Library-conneg.md +++ b/Library-conneg.md @@ -11,8 +11,8 @@ The user agent (a web browser, for example. or the curl program), can request di Next, we need to declare all the representations we support: -` mime_types_supported: LINKED_LIST [STRING] is - -- Media types 'Current' supports + mime_types_supported: LINKED_LIST [STRING] is + -- Media types `Current' supports once create Result.make Result.put_front ({HTTP_MIME_TYPES}.application_xml) @@ -23,7 +23,7 @@ Next, we need to declare all the representations we support: end charsets_supported: LINKED_LIST [STRING] is - -- Character sets 'Current' supports + -- Character sets `Current' supports once create Result.make Result.put_front ("UTF-8") @@ -33,7 +33,7 @@ Next, we need to declare all the representations we support: end encodings_supported: LINKED_LIST [STRING] is - -- Encodings 'Current' supports + -- Encodings `Current' supports once create Result.make Result.put_front ("identity") @@ -44,7 +44,7 @@ Next, we need to declare all the representations we support: end languages_supported: LINKED_LIST [STRING] is - -- Languages 'Current' supports + -- Languages `Current' supports once create Result.make Result.put_front ("en") @@ -55,8 +55,8 @@ Next, we need to declare all the representations we support: Now we are in a position to do some negotiating. At the beginning of your handler(s), code: -` -local + + local l_media_variants: MEDIA_TYPE_VARIANT_RESULTS do l_media_variants:= conneg.media_type_preference (mime_types_supported, a_req.http_accept) From f6d64b42c66dad6392ba4e2290d0d5afd38208d6 Mon Sep 17 00:00:00 2001 From: colin-adams Date: Fri, 15 Jun 2012 08:38:30 -0700 Subject: [PATCH 09/13] Complete. --- Library-conneg.md | 120 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 117 insertions(+), 3 deletions(-) diff --git a/Library-conneg.md b/Library-conneg.md index 4bf63725..79b9d15f 100644 --- a/Library-conneg.md +++ b/Library-conneg.md @@ -58,17 +58,131 @@ Now we are in a position to do some negotiating. At the beginning of your handle local l_media_variants: MEDIA_TYPE_VARIANT_RESULTS + l_is_head: BOOLEAN + h: HTTP_HEADER + l_msg: STRING do + l_is_head := False -- or `True' if this is for a HEAD handler l_media_variants:= conneg.media_type_preference (mime_types_supported, a_req.http_accept) if not l_media_variants.is_acceptable then - send_unacceptable_media_type (a_res) + send_unacceptable_media_type (a_res, l_is_head) elseif not conneg.charset_preference (charsets_supported, a_req.http_accept_charset).is_acceptable then - send_unacceptable_charset (a_res) + send_unacceptable_charset (a_res, l_is_head) elseif not conneg.encoding_preference (encodings_supported, a_req.http_accept_encoding).is_acceptable then - send_unacceptable_encoding (a_res) + send_unacceptable_encoding (a_res, l_is_head) elseif not conneg.language_preference (languages_supported, a_req.http_accept_language).is_acceptable then send_unacceptable_encoding (a_res) else -- We have agreed a representation, let's go and serve it to the client ` +Now for those `send_unnacceptable_...` routines. They are fairly simple: + + send_unacceptable_media_type (a_res: WSF_RESPONSE; a_is_head: BOOLEAN) is + -- Send error result as text/plain that the media type is unnacceptable. + require + a_res_not_void: a_res /= Void + status_not_set: not a_res.status_is_set + header_not_committed: not a_res.header_committed + local + l_error_text: STRING + do + l_error_text := "The requested media type(s) is/are not supported by this server." + send_unacceptable (a_res, a_is_head, l_error_text) + end + + send_unacceptable_charset (a_res: WSF_RESPONSE; a_is_head: BOOLEAN) is + -- Send error result as text/plain that the character set is unnacceptable. + require + a_res_not_void: a_res /= Void + status_not_set: not a_res.status_is_set + header_not_committed: not a_res.header_committed + local + l_error_text: STRING + do + l_error_text := "The requested character set(s) is/are not supported by this server. Only UTF-8 is supported." + send_unacceptable (a_res, a_is_head, l_error_text) + end + + send_unacceptable_encoding (a_res: WSF_RESPONSE; a_is_head: BOOLEAN) is + -- Send error result as text/plain that the encoding is unnacceptable. + require + a_res_not_void: a_res /= Void + status_not_set: not a_res.status_is_set + header_not_committed: not a_res.header_committed + local + l_error_text: STRING + do + l_error_text := "The requested encoding(s) is/are not supported by this server. Only identity is supported." + send_unacceptable (a_res, a_is_head, l_error_text) + end + + send_unacceptable_language (a_res: WSF_RESPONSE; a_is_head: BOOLEAN) is + -- Send error result as text/plain that the language unnacceptable. + require + a_res_not_void: a_res /= Void + status_not_set: not a_res.status_is_set + header_not_committed: not a_res.header_committed + local + l_error_text: STRING + do + l_error_text := "The requested language(s) is/are not supported by this server. Only en (English) is supported." + send_unacceptable (a_res, a_is_head, l_error_text) + end + + send_unacceptable (a_res: WSF_RESPONSE; a_is_head: BOOLEAN; a_error_text: STRING) is + -- Send a_error_text as text/plain that a header is unnacceptable. + require + a_res_not_void: a_res /= Void + status_not_set: not a_res.status_is_set + header_not_committed: not a_res.header_committed + a_error_text_not_void: a_error_text /= Void + local + h: HTTP_HEADER + do + create h.make + set_content_type (h, Void) + h.put_content_length (a_error_text.count) + h.put_current_date + a_res.set_status_code ({HTTP_STATUS_CODE}.not_acceptable) + a_res.put_header_text (h.string) + if not a_is_head then + a_res.put_string (a_error_text) + end + end + +We'll see that `set_content_type` routine in a bit. But for now, we just have to generate the response. Let's go back to that `else ...` bit: + + else + -- We have agreed a representation, let's go and serve it to the client + create h.make + set_content_type (h, a_media_variants) + if a_media_variants.media_type ~ {HTTP_MIME_TYPES}.application_xml then + l_msg := "etc." + else + l_msg := json.value ().representation + end + h.put_content_length (l_msg.count) + h.put_current_date + a_res.set_status_code ({HTTP_STATUS_CODE}.ok) + a_res.put_header_text (h.string) + if not a_is_head then + a_res.put_string (l_msg) + end + +There's that `set_content_type` again. Finally, we will take a look at it: + + set_content_type (a_h: HTTP_HEADER; a_media_variants: MEDIA_TYPE_VARIANT_RESULTS) is + -- Set the content=type header in `a_h' according to `a_media_variants'. + require + a_h_not_void: a_h /= Void + do + if a_media_variants = Void or else not a_media_variants.is_acceptable then + a_h.put_content_type ({HTTP_MIME_TYPES}.text_plain) + else + a_h.put_content_type (a_media_variants.media_type) + end + a_h.put_header_key_value ({HTTP_HEADER_NAMES}.header_vary, {HTTP_HEADER_NAMES}.header_accept) + end + +Firstly, if we haven't agreed a media-type, then we send our (negative) response as `plain/text`. Otherwise we will send the response in the agreed media-type. But in each case we add a `Vary:Accept` header. This tells proxy caches that they have to check the media-type before returning a cached result, as there may be a different representation available. Since we do not vary our representation by language, charset or encoding, we don't add `Vary:Accept-Language,Accept-Charset,Accept-Encoding`. But if we were to negotiate different representations on those dimensions also, we would need to list the appropriate headers in the `Vary` header. \ No newline at end of file From ca6b4c468fc892b82fbae5b6337ce49564fde2ca Mon Sep 17 00:00:00 2001 From: jocelyn Date: Wed, 20 Jun 2012 12:53:52 -0700 Subject: [PATCH 10/13] Updated Tasks Roadmap (markdown) --- Tasks-Roadmap.md | 59 ++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/Tasks-Roadmap.md b/Tasks-Roadmap.md index e4aece3c..7bb685de 100644 --- a/Tasks-Roadmap.md +++ b/Tasks-Roadmap.md @@ -1,36 +1,35 @@ -## October 1st ## -* Source code , layout/handling EWR (**jfiat**) -* "Eiffel WSGI" spec (github wiki) (**paco**) -* Eiffel Web Nino (**jvelilla**) -* REST component (**jfiat**) -* Example/reference Eiffel Web Server App (**jvelilla**) - - Hello World - - Restbucks (from the book REST in Practice) -* WAMIE/apache based support for Eiffel WSGI (**daro**) - - SCOOP ... -* Some persistance solution (**daro**) -* XML, [[JSON|Task-JSON]] support (**jvelilla**) +## Future +* Focus on REST API + - Hypermedia API + - HAL, Collection/JSON ... + - ATOM, RSS, XHTML, ... ? +* Extend WSF with libraries addressing common needs + - Logging + - Caching + - Security (authentication) + OAuth (consumer+provider) + OpenID? + - Filter chain -## Maybe for October 1st ## -* Reference Client/REST-service consumer (**jfiat**) -* Mashup support, facebook, twitter, google+, ... (**jfiat**) -* Authentication support (**jfiat** ?) - - OpenID, Google Connect, Facebook Connect, OAuth, ... - - http authorization +* Start thinking about application friendly libraries + - Template engine + - State machine + - HTML5 (XHTML+JS) generation for widgets (table, suggestive box, ...) + - Google API, Twitter API, ... ? -## December ## -* Session handling - - Cookie based - - REST-based session example -* Access Control -* Application builder - - Deployment - - Persistence chooser -* Dynamic update of running system (**daro**) +* Improve documentation + - WSF documentation + tutorial + - Topic: how to contribute ? + - Example: add a "graphviz server" example, which will demonstrate an REST Hypermedia API, with logging, caching and security + +## Version 0.1 june 2012 ## +* "Eiffel WSGI" spec +* Core of Eiffel Web Framework + - EWSGI connectors: CGI, libfcgi, Nino + - WSF: request, response, router + - And utility lib, error, http, encoders, ...) +* Examples +* Documentation (tutorial inside the examples folder) +* Installation scripts ## Contributors ## - See [[the collaboration page|Community-collaboration]] -note: In bold, you see the responsible for each task, but contribution from other is possible as well. - -This needs updating, I think. \ No newline at end of file From 3d686fb50ca410586d9b8ae35d7727fbf04093af Mon Sep 17 00:00:00 2001 From: jocelyn Date: Wed, 20 Jun 2012 12:54:37 -0700 Subject: [PATCH 11/13] Updated Task json (markdown) --- Task-json.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Task-json.md b/Task-json.md index f4ccd3fe..8b25b368 100644 --- a/Task-json.md +++ b/Task-json.md @@ -7,4 +7,5 @@ - and then let Eiffel Software include it, in the official libraries ## Roadmap ## -- this should be done before 1st of October - so has this been achieved? \ No newline at end of file +- This task is completed. +- Future task: review the library, and improve it. \ No newline at end of file From 675f58f42b036a88a42081131ef0d74f123e15ba Mon Sep 17 00:00:00 2001 From: jocelyn Date: Wed, 20 Jun 2012 12:56:55 -0700 Subject: [PATCH 12/13] Updated Community collaboration (markdown) --- Community-collaboration.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Community-collaboration.md b/Community-collaboration.md index 58098906..13819d95 100644 --- a/Community-collaboration.md +++ b/Community-collaboration.md @@ -10,11 +10,16 @@ This project is a community project - Proposal from Paul Cohen for a EWSGI spec at http://eiffel.seibostudios.se/wiki/EWSGI ## Main contributors ## -- **jfiat**: Jocelyn Fiat (Eiffel Software | http://eiffel.com/) -- **jvelilla**: Hector Javier Velilla (Seibo Software Studios | http://http://seibostudios.se/en/) -- **paco**: Paul Cohen (Seibo Software Studios | http://http://seibostudios.se/en/) -- **daro**: Daniel Rodriguez (Seibo Software Studios | http://http://seibostudios.se/en/) +- **jfiat**: Jocelyn Fiat (Eiffel Software) +- **jvelilla**: Hector Javier Velilla (Seibo Software Studios) +- **paco**: Paul Cohen (Seibo Software Studios) +- **daro**: Daniel Rodriguez (Seibo Software Studios) +- Olivier Ligot (Groupe-S) +- Paul G.Crismer (Groupe-S) +- Berend de Boer (XplainHosting) +- Colin Adams (AXA R.) +- Alexander Kogtenkov (Eiffel Software) ## You want to participate ## - You are welcome to contribute (code, test, doc, code review, feedback, suggestion, spread the words ...) -- Feel free to subscribe to the mailing list +- Feel free to subscribe to the mailing list \ No newline at end of file From 9adbee9887fd1f4df3eeb571ea844283cadf321f Mon Sep 17 00:00:00 2001 From: jocelyn Date: Thu, 28 Jun 2012 22:39:41 -0700 Subject: [PATCH 13/13] Updated EWSGI specification: difference in main proposals (markdown) --- ...ls.md => EWSGI-specification---difference-in-main-proposals.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename EWSGI-specification:-difference-in-main-proposals.md => EWSGI-specification---difference-in-main-proposals.md (100%) diff --git a/EWSGI-specification:-difference-in-main-proposals.md b/EWSGI-specification---difference-in-main-proposals.md similarity index 100% rename from EWSGI-specification:-difference-in-main-proposals.md rename to EWSGI-specification---difference-in-main-proposals.md