├── clients ├── go │ ├── .gitignore │ ├── Procfile │ ├── manifest.yml │ └── main.go ├── ruby │ ├── ruby-rails │ │ ├── log │ │ │ └── .keep │ │ ├── tmp │ │ │ └── .keep │ │ ├── lib │ │ │ └── tasks │ │ │ │ └── .keep │ │ ├── test │ │ │ ├── fixtures │ │ │ │ ├── .keep │ │ │ │ └── files │ │ │ │ │ └── .keep │ │ │ ├── mailers │ │ │ │ └── .keep │ │ │ ├── models │ │ │ │ └── .keep │ │ │ ├── controllers │ │ │ │ └── .keep │ │ │ ├── integration │ │ │ │ └── .keep │ │ │ └── test_helper.rb │ │ ├── app │ │ │ ├── models │ │ │ │ ├── concerns │ │ │ │ │ └── .keep │ │ │ │ └── application_record.rb │ │ │ ├── controllers │ │ │ │ ├── concerns │ │ │ │ │ └── .keep │ │ │ │ ├── application_controller.rb │ │ │ │ └── feedback_controller.rb │ │ │ ├── views │ │ │ │ └── layouts │ │ │ │ │ ├── mailer.text.erb │ │ │ │ │ └── mailer.html.erb │ │ │ ├── jobs │ │ │ │ └── application_job.rb │ │ │ ├── channels │ │ │ │ └── application_cable │ │ │ │ │ ├── channel.rb │ │ │ │ │ └── connection.rb │ │ │ └── mailers │ │ │ │ └── application_mailer.rb │ │ ├── config │ │ │ ├── boot.rb │ │ │ ├── spring.rb │ │ │ ├── environment.rb │ │ │ ├── cable.yml │ │ │ ├── initializers │ │ │ │ ├── mime_types.rb │ │ │ │ ├── application_controller_renderer.rb │ │ │ │ ├── filter_parameter_logging.rb │ │ │ │ ├── backtrace_silencers.rb │ │ │ │ ├── wrap_parameters.rb │ │ │ │ ├── cors.rb │ │ │ │ ├── inflections.rb │ │ │ │ └── new_framework_defaults.rb │ │ │ ├── routes.rb │ │ │ ├── database.yml │ │ │ ├── locales │ │ │ │ └── en.yml │ │ │ ├── secrets.yml │ │ │ ├── application.rb │ │ │ └── environments │ │ │ │ ├── development.rb │ │ │ │ └── test.rb │ │ ├── config.ru │ │ ├── public │ │ │ └── robots.txt │ │ ├── Rakefile │ │ ├── README.md │ │ ├── db │ │ │ └── seeds.rb │ │ ├── .gitignore │ │ └── Gemfile │ └── sinatra │ │ ├── Rakefile │ │ ├── README.md │ │ ├── lib │ │ └── extreme-carpaccio.rb │ │ └── tests │ │ └── test_exterme-carpaccio.rb ├── racket │ ├── .gitignore │ ├── carpaccio.rkt │ └── README.md ├── java │ ├── java-spark │ │ ├── .gitignore │ │ ├── README.md │ │ ├── src │ │ │ └── main │ │ │ │ └── java │ │ │ │ └── extremecarpaccio │ │ │ │ ├── JsonResponseTransformer.java │ │ │ │ └── Strings.java │ │ └── pom.xml │ ├── java-fluent-http │ │ ├── .gitignore │ │ ├── src │ │ │ ├── main │ │ │ │ └── java │ │ │ │ │ └── xcarpaccio │ │ │ │ │ ├── Answer.java │ │ │ │ │ ├── Logger.java │ │ │ │ │ ├── MyFluentHttpServer.java │ │ │ │ │ ├── Message.java │ │ │ │ │ ├── Order.java │ │ │ │ │ └── WebConfiguration.java │ │ │ └── test │ │ │ │ └── java │ │ │ │ └── xcarpaccio │ │ │ │ └── MyFluentHttpServerTest.java │ │ ├── README.md │ │ └── pom.xml │ ├── java-springboot │ │ └── src │ │ │ ├── main │ │ │ ├── resources │ │ │ │ └── application.properties │ │ │ └── java │ │ │ │ └── xcarpaccio │ │ │ │ ├── Amount.java │ │ │ │ ├── CarpaccioApplication.java │ │ │ │ ├── FeedbackMessage.java │ │ │ │ ├── Order.java │ │ │ │ └── WebController.java │ │ │ └── test │ │ │ └── java │ │ │ └── xcarpaccio │ │ │ ├── WebControllerBusinessTest.java │ │ │ ├── WebControllerMockedServerTest.java │ │ │ └── WebControllerServerTest.java │ └── java-httpserver │ │ ├── manifest.yml │ │ ├── src │ │ ├── main │ │ │ └── java │ │ │ │ └── xcarpaccio │ │ │ │ ├── Result.java │ │ │ │ ├── StringUtils.java │ │ │ │ ├── Logger.java │ │ │ │ ├── Order.java │ │ │ │ └── FeedbackMessage.java │ │ └── test │ │ │ └── java │ │ │ └── xcarpaccio │ │ │ ├── AbstractHttpServerTest.java │ │ │ └── MyHttpServerTest.java │ │ ├── README.md │ │ └── .gitignore ├── javascript │ ├── node-plain │ │ ├── .gitignore │ │ ├── conf.js │ │ ├── main.js │ │ ├── README.md │ │ ├── lib │ │ │ └── logic.js │ │ ├── package.json │ │ └── specs │ │ │ └── server_spec.js │ └── express │ │ ├── lib │ │ ├── process.js │ │ └── routes.js │ │ ├── test │ │ ├── 200-process-order.js │ │ └── 000-server-start.js │ │ ├── README.md │ │ ├── package.json │ │ └── server.js ├── php │ ├── silex │ │ ├── .gitignore │ │ ├── web │ │ │ └── app.php │ │ ├── src │ │ │ └── ExtremeCarpaccio │ │ │ │ └── Model │ │ │ │ └── Order.php │ │ ├── tests │ │ │ ├── units │ │ │ │ ├── Test.php │ │ │ │ └── src │ │ │ │ │ └── ExtremeCarpaccio │ │ │ │ │ └── Model │ │ │ │ │ ├── OrderProduct.php │ │ │ │ │ └── Order.php │ │ │ └── functionals │ │ │ │ └── features │ │ │ │ ├── Ping.feature │ │ │ │ ├── bootstrap │ │ │ │ └── ExtremeCarpaccio │ │ │ │ │ ├── FeatureContext.php │ │ │ │ │ ├── ApiContext.php │ │ │ │ │ └── ApiContext │ │ │ │ │ └── PingContext.php │ │ │ │ └── Order.feature │ │ ├── README.md │ │ ├── docker │ │ │ ├── php │ │ │ │ └── Dockerfile │ │ │ └── nginx │ │ │ │ └── site.conf │ │ ├── docker-compose.yml │ │ ├── .bootstrap.atoum.php │ │ ├── behat.yml │ │ ├── composer.json │ │ └── Makefile │ ├── native │ │ ├── .gitignore │ │ ├── tests │ │ │ ├── functionals │ │ │ │ └── casperjs │ │ │ │ │ ├── 01-index.js │ │ │ │ │ ├── 02-ping.js │ │ │ │ │ ├── 04-feedback.js │ │ │ │ │ └── 03-order.js │ │ │ └── units │ │ │ │ ├── Test.php │ │ │ │ └── src │ │ │ │ └── ExtremeCarpaccio │ │ │ │ └── Model │ │ │ │ ├── OrderProduct.php │ │ │ │ └── Order.php │ │ ├── src │ │ │ └── ExtremeCarpaccio │ │ │ │ └── Model │ │ │ │ └── Order.php │ │ ├── docker │ │ │ ├── php │ │ │ │ └── Dockerfile │ │ │ └── nginx │ │ │ │ └── site.conf │ │ ├── web │ │ │ └── app.php │ │ ├── docker-compose.yml │ │ ├── composer.json │ │ ├── README.md │ │ ├── .bootstrap.atoum.php │ │ └── Makefile │ └── socket │ │ ├── .gitignore │ │ ├── README.md │ │ ├── src │ │ ├── OutputInterface.php │ │ ├── ResponseInterface.php │ │ ├── FeedbackMapperInterface.php │ │ ├── Console.php │ │ ├── Result.php │ │ ├── Order.php │ │ ├── ReaderInterface.php │ │ ├── FeedbackMessage.php │ │ ├── JsonFeedbackMapper.php │ │ ├── Starter.php │ │ ├── Response.php │ │ ├── Server.php │ │ └── Reader.php │ │ ├── composer.json │ │ └── tests │ │ ├── TestOrder.php │ │ └── TestJsonFeedbackMapper.php ├── scala │ ├── .gitignore │ ├── project │ │ ├── build.properties │ │ └── Dependencies.scala │ ├── README.md │ ├── build.sbt │ └── src │ │ └── main │ │ └── scala │ │ └── main │ │ └── Server.scala ├── clojure │ ├── .gitignore │ ├── src │ │ ├── user.clj │ │ └── extremecarpaccio │ │ │ └── core.clj │ ├── test │ │ └── extremecarpaccio │ │ │ └── core_test.clj │ ├── project.clj │ └── README.md ├── c# │ ├── dnx-csharp │ │ ├── watch-web.sh │ │ ├── watch-tests.sh │ │ ├── global.json │ │ ├── NuGet.config │ │ ├── src │ │ │ └── xcarpaccio │ │ │ │ ├── models.cs │ │ │ │ ├── startup.cs │ │ │ │ ├── app.cs │ │ │ │ ├── project.json │ │ │ │ └── modules.cs │ │ ├── test │ │ │ └── xcarpaccio.tests │ │ │ │ ├── tests.cs │ │ │ │ └── project.json │ │ ├── build.sh │ │ └── .vscode │ │ │ ├── tasks.json │ │ │ └── launch.json │ ├── coreWebApi │ │ ├── src │ │ │ └── xcarpaccio │ │ │ │ ├── Models │ │ │ │ ├── Order.cs │ │ │ │ └── Feedback.cs │ │ │ │ ├── appsettings.json │ │ │ │ ├── Controllers │ │ │ │ ├── Home.cs │ │ │ │ ├── OrderController.cs │ │ │ │ └── FeedbackController.cs │ │ │ │ ├── web.config │ │ │ │ ├── Program.cs │ │ │ │ ├── RequestLoggerMiddleware.cs │ │ │ │ ├── project.json │ │ │ │ └── Startup.cs │ │ ├── global.json │ │ ├── readme.md │ │ ├── Dockerfile │ │ ├── NuGet.config │ │ ├── test │ │ │ └── xcarpaccio.tests │ │ │ │ ├── feedbackTest.cs │ │ │ │ └── project.json │ │ └── .vscode │ │ │ ├── tasks.json │ │ │ └── launch.json │ └── nancy │ │ ├── NancyApplication1 │ │ ├── Content │ │ │ └── nancy-logo.png │ │ ├── packages.config │ │ ├── IndexModule.cs │ │ ├── Bootstrapper.cs │ │ ├── Views │ │ │ └── index.sshtml │ │ ├── Program.cs │ │ └── Properties │ │ │ └── AssemblyInfo.cs │ │ ├── extreme-carpaccio.client │ │ ├── Bill.cs │ │ ├── Feedback.cs │ │ ├── packages.config │ │ ├── Order.cs │ │ ├── Bootstrapper.cs │ │ ├── Program.cs │ │ ├── Properties │ │ │ └── AssemblyInfo.cs │ │ └── IndexModule.cs │ │ ├── README.md │ │ └── extreme-carpaccio.client.sln ├── kotlin │ ├── settings.gradle │ ├── src │ │ ├── main │ │ │ ├── resources │ │ │ │ └── simplelogger.properties │ │ │ └── kotlin │ │ │ │ └── xcarpaccio │ │ │ │ ├── Result.kt │ │ │ │ ├── Order.kt │ │ │ │ └── Logger.kt │ │ └── test │ │ │ └── resources │ │ │ └── mockito-extensions │ │ │ └── org.mockito.plugins.MockMaker │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── README.md │ ├── build.gradle │ └── .gitignore ├── haskell │ ├── .gitignore │ ├── tdd.sh │ ├── test │ │ └── Spec.hs │ ├── src │ │ ├── Model.hs │ │ └── Main.hs │ ├── README.md │ └── carpaccio.cabal ├── erlang │ ├── .gitignore │ ├── rebar │ ├── src │ │ ├── xcarpaccio.erl │ │ ├── xcarpaccio.app.src │ │ └── xcarpaccio_app.erl │ ├── rebar.config │ ├── test │ │ └── jsx_usage_test.erl │ └── README.md ├── python │ ├── flask-server │ │ ├── __main__.py │ │ ├── README.md │ │ └── client │ │ │ └── __init__.py │ ├── simple-server │ │ ├── __main__.py │ │ └── README.md │ └── simple-server-python3 │ │ ├── __main__.py │ │ ├── client │ │ └── __init__.pyc │ │ └── README.md ├── f# │ ├── carpaccio-client │ │ ├── paket.references │ │ ├── App.config │ │ ├── carpaccio-model.fs │ │ └── carpaccio-client.fs │ ├── .gitignore │ ├── .paket │ │ └── paket.bootstrapper.exe │ ├── paket.dependencies │ ├── paket.lock │ ├── build.cmd │ ├── README.md │ ├── build.sh │ ├── build.fsx │ └── extreme-carpaccio.sln ├── groovy │ └── groovy-ratpack │ │ ├── .gitignore │ │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ │ ├── README.md │ │ ├── src │ │ ├── ratpack │ │ │ └── Ratpack.groovy │ │ └── test │ │ │ └── groovy │ │ │ └── ExtremeCarpaccioSpec.groovy │ │ └── build.gradle ├── typescript │ ├── src │ │ ├── calc.ts │ │ ├── calc.spec.ts │ │ └── server.ts │ ├── tsconfig.json │ └── package.json ├── d │ ├── source │ │ ├── models │ │ │ ├── feedback.d │ │ │ └── order.d │ │ ├── utils.d │ │ └── app.d │ ├── dub.json │ ├── .gitignore │ └── README.md └── rust │ ├── Cargo.toml │ └── src │ └── main.rs ├── server ├── .bowerrc ├── manifest.yml ├── public │ └── stylesheets │ │ └── style.css ├── javascripts │ ├── services │ │ ├── index.js │ │ ├── reduction.js │ │ └── order.js │ ├── utils.js │ ├── routes.js │ └── config.js ├── configuration.json ├── bower.json ├── .eslintrc ├── specs │ ├── investigating_spec.js │ ├── config_spec.js │ └── utils_spec.js ├── package.json ├── app.js └── bin │ └── www ├── .travis.yml ├── .github ├── dependabot.yml └── workflows │ ├── on-all-prs.yml │ └── on-prs-made-against-the-server.yml ├── .gitignore ├── LICENSE └── README.md /clients/go/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | -------------------------------------------------------------------------------- /clients/go/Procfile: -------------------------------------------------------------------------------- 1 | web: go 2 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/log/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/tmp/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /clients/racket/.gitignore: -------------------------------------------------------------------------------- 1 | compiled 2 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/lib/tasks/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/test/fixtures/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/test/mailers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/test/models/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /clients/java/java-spark/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/test/controllers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/test/integration/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/app/models/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/test/fixtures/files/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /clients/javascript/node-plain/.gitignore: -------------------------------------------------------------------------------- 1 | npm-debug.log 2 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/app/controllers/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /clients/php/silex/.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | 3 | composer.lock 4 | -------------------------------------------------------------------------------- /clients/scala/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | target 3 | project/target -------------------------------------------------------------------------------- /clients/scala/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version = 0.13.15 -------------------------------------------------------------------------------- /server/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "public/components" 3 | } -------------------------------------------------------------------------------- /clients/clojure/.gitignore: -------------------------------------------------------------------------------- 1 | .lein-failures 2 | .nrepl-port 3 | target/ -------------------------------------------------------------------------------- /clients/php/native/.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | 3 | composer.lock 4 | -------------------------------------------------------------------------------- /clients/java/java-fluent-http/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | .idea 3 | *.iml 4 | -------------------------------------------------------------------------------- /clients/c#/dnx-csharp/watch-web.sh: -------------------------------------------------------------------------------- 1 | cd test/xcarpaccio 2 | dnx-watch web 3 | -------------------------------------------------------------------------------- /clients/kotlin/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'extreme-carpaccio' 2 | 3 | -------------------------------------------------------------------------------- /clients/php/native/tests/functionals/casperjs/01-index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/app/views/layouts/mailer.text.erb: -------------------------------------------------------------------------------- 1 | <%= yield %> 2 | -------------------------------------------------------------------------------- /clients/haskell/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | .cabal-sandbox 3 | cabal.sandbox.config 4 | -------------------------------------------------------------------------------- /clients/c#/dnx-csharp/watch-tests.sh: -------------------------------------------------------------------------------- 1 | cd test/xcarpaccio.tests 2 | dnx-watch test 3 | -------------------------------------------------------------------------------- /clients/erlang/.gitignore: -------------------------------------------------------------------------------- 1 | .eunit 2 | .rebar/ 3 | deps/ 4 | ebin/ 5 | erl_crash.dump 6 | -------------------------------------------------------------------------------- /clients/java/java-springboot/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8090 -------------------------------------------------------------------------------- /clients/php/socket/.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | .idea/ 3 | .DS_Store 4 | composer.lock 5 | -------------------------------------------------------------------------------- /clients/python/flask-server/__main__.py: -------------------------------------------------------------------------------- 1 | import client 2 | 3 | client.start_server() 4 | -------------------------------------------------------------------------------- /clients/python/simple-server/__main__.py: -------------------------------------------------------------------------------- 1 | import client 2 | 3 | client.start_server() -------------------------------------------------------------------------------- /clients/f#/carpaccio-client/paket.references: -------------------------------------------------------------------------------- 1 | Suave 2 | Newtonsoft.Json 3 | FSharp.Core 4 | -------------------------------------------------------------------------------- /clients/python/simple-server-python3/__main__.py: -------------------------------------------------------------------------------- 1 | import client 2 | 3 | client.start_server() -------------------------------------------------------------------------------- /clients/erlang/rebar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dlresende/extreme-carpaccio/HEAD/clients/erlang/rebar -------------------------------------------------------------------------------- /clients/kotlin/src/main/resources/simplelogger.properties: -------------------------------------------------------------------------------- 1 | org.slf4j.simpleLogger.defaultLogLevel=error -------------------------------------------------------------------------------- /clients/kotlin/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker: -------------------------------------------------------------------------------- 1 | mock-maker-inline -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | class ApplicationJob < ActiveJob::Base 2 | end 3 | -------------------------------------------------------------------------------- /clients/javascript/node-plain/conf.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | port: 1337, 3 | host: "127.0.0.1" 4 | } 5 | -------------------------------------------------------------------------------- /clients/f#/.gitignore: -------------------------------------------------------------------------------- 1 | .fake/ 2 | build/ 3 | deploy/ 4 | packages/ 5 | bin/ 6 | obj/ 7 | .paket/paket.exe 8 | 9 | -------------------------------------------------------------------------------- /clients/groovy/groovy-ratpack/.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | build 3 | .gradle 4 | .project 5 | .settings 6 | .classpath 7 | -------------------------------------------------------------------------------- /clients/php/socket/README.md: -------------------------------------------------------------------------------- 1 | Use composer to get dependencies 2 | 3 | $ composer install 4 | 5 | Run Starter.php -------------------------------------------------------------------------------- /clients/javascript/express/lib/process.js: -------------------------------------------------------------------------------- 1 | exports.order = function order(input, onResult) { 2 | onResult(null, {}); 3 | } 4 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::API 2 | end 3 | -------------------------------------------------------------------------------- /clients/typescript/src/calc.ts: -------------------------------------------------------------------------------- 1 | // more of your code here 2 | 3 | export function sayHello() { 4 | return "Hello World"; 5 | } -------------------------------------------------------------------------------- /clients/c#/coreWebApi/src/xcarpaccio/Models/Order.cs: -------------------------------------------------------------------------------- 1 | namespace XCarpaccio.Models 2 | { 3 | public class Order 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /clients/d/source/models/feedback.d: -------------------------------------------------------------------------------- 1 | module models.feedback; 2 | 3 | struct Feedback 4 | { 5 | string type; 6 | string content; 7 | } -------------------------------------------------------------------------------- /clients/f#/.paket/paket.bootstrapper.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dlresende/extreme-carpaccio/HEAD/clients/f#/.paket/paket.bootstrapper.exe -------------------------------------------------------------------------------- /clients/php/socket/src/OutputInterface.php: -------------------------------------------------------------------------------- 1 | (default port is 5000) 6 | 7 | dotnet test .\test\xcarpaccio.tests to run tests -------------------------------------------------------------------------------- /clients/c#/dnx-csharp/global.json: -------------------------------------------------------------------------------- 1 | { 2 | "projects": [ 3 | "src", 4 | "test" 5 | ], 6 | "sdk": { 7 | "version": "1.0.0-preview2-1-003177" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /clients/c#/nancy/extreme-carpaccio.client/Bill.cs: -------------------------------------------------------------------------------- 1 | namespace xCarpaccio.client 2 | { 3 | class Bill 4 | { 5 | public decimal total { get; set; } 6 | 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /clients/javascript/node-plain/main.js: -------------------------------------------------------------------------------- 1 | var conf = require('./conf'), 2 | server = require('./lib/server'), 3 | applyLogic = require('./lib/logic'); 4 | 5 | server.start(conf, applyLogic); 6 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: async 3 | 4 | test: 5 | adapter: async 6 | 7 | production: 8 | adapter: redis 9 | url: redis://localhost:6379/1 10 | -------------------------------------------------------------------------------- /clients/php/socket/src/Console.php: -------------------------------------------------------------------------------- 1 | true]); 8 | 9 | 10 | $app->run(); 11 | -------------------------------------------------------------------------------- /clients/clojure/src/user.clj: -------------------------------------------------------------------------------- 1 | (ns user 2 | (:require [ring.adapter.jetty :refer [run-jetty]] 3 | [extremecarpaccio.core :refer :all])) 4 | 5 | (defonce server (run-jetty #'my-app {:port 4000 :join? false})) 6 | -------------------------------------------------------------------------------- /clients/f#/paket.lock: -------------------------------------------------------------------------------- 1 | NUGET 2 | remote: https://www.nuget.org/api/v2 3 | specs: 4 | FAKE (4.28) 5 | FSharp.Core (4.0.0.1) 6 | Newtonsoft.Json (8.0.3) 7 | Suave (1.1.2) 8 | FSharp.Core (>= 3.1.2.5) 9 | -------------------------------------------------------------------------------- /clients/c#/nancy/extreme-carpaccio.client/Feedback.cs: -------------------------------------------------------------------------------- 1 | namespace xCarpaccio.client 2 | { 3 | class Feedback 4 | { 5 | public string type { get; set; } 6 | public string content { get; set; } 7 | 8 | } 9 | } -------------------------------------------------------------------------------- /clients/php/socket/src/Result.php: -------------------------------------------------------------------------------- 1 | total = $result; 10 | } 11 | 12 | 13 | 14 | } -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /clients/f#/carpaccio-client/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /clients/haskell/tdd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | while true; do 4 | 5 | cabal test --test-option=--color 6 | echo "" 7 | 8 | inotifywait -qr -e modify -e create -e move -e delete src test --exclude "\.\#.*" 9 | done 10 | -------------------------------------------------------------------------------- /clients/java/java-fluent-http/src/main/java/xcarpaccio/Answer.java: -------------------------------------------------------------------------------- 1 | package xcarpaccio; 2 | 3 | public class Answer { 4 | public Double total; 5 | 6 | public Answer(double total) { 7 | this.total = total; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html 3 | post :feedback, controller: :feedback 4 | end 5 | -------------------------------------------------------------------------------- /clients/c#/nancy/README.md: -------------------------------------------------------------------------------- 1 | WELCOME TO NANCY :-), 2 | 3 | IF YOU DON'T HAVE NANCY YET, INSTALL THE NANCY PROJECT TEMPLATES FROM EXTENSIONS AND UPDATES - TOOLS 4 | 5 | BUILD TO RUN ANYWHERE, 6 | THIS IS A SELFHOSTING NANCY APPLICATION, JUST RUN IT -------------------------------------------------------------------------------- /clients/php/silex/src/ExtremeCarpaccio/Model/Order.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /clients/kotlin/src/main/kotlin/xcarpaccio/Order.kt: -------------------------------------------------------------------------------- 1 | package xcarpaccio 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class Order(val prices: List, val quantities: List, val country: String, val reduction: String) { 7 | 8 | } -------------------------------------------------------------------------------- /clients/php/socket/src/Order.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require_relative 'config/application' 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /clients/php/socket/src/ReaderInterface.php: -------------------------------------------------------------------------------- 1 | mockGenerator->allIsInterface(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /clients/java/java-httpserver/manifest.yml: -------------------------------------------------------------------------------- 1 | --- 2 | applications: 3 | - name: extreme-carpaccio-java-http-server 4 | memory: 1G 5 | instances: 1 6 | path: target/extreme-carpaccio-java-httpserver-1.0-SNAPSHOT-jar-with-dependencies.jar 7 | buildpack: https://github.com/cloudfoundry/java-buildpack.git 8 | -------------------------------------------------------------------------------- /clients/php/native/tests/units/Test.php: -------------------------------------------------------------------------------- 1 | mockGenerator->allIsInterface(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /clients/d/dub.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "Diego Lemos", "rgeorges" 4 | ], 5 | "copyright": " ", 6 | "dependencies": { 7 | "vibe-d": "~>0.8.6-rc.1" 8 | }, 9 | "description": "extreme-carpaccio D language client.", 10 | "license": "public", 11 | "name": "extreme-carpaccio-server" 12 | } -------------------------------------------------------------------------------- /clients/java/java-springboot/src/main/java/xcarpaccio/Amount.java: -------------------------------------------------------------------------------- 1 | package xcarpaccio; 2 | 3 | public class Amount { 4 | 5 | public Double total; 6 | 7 | public Amount(Double total) { 8 | this.total = total; 9 | } 10 | 11 | public Amount() {} //for test only 12 | } 13 | 14 | -------------------------------------------------------------------------------- /clients/javascript/express/lib/routes.js: -------------------------------------------------------------------------------- 1 | exports.order = function order(req, res, next) { 2 | // TODO implement from here 3 | res.json({}); 4 | } 5 | 6 | exports.feedback = function feedback(req, res, next) { 7 | console.info("FEEDBACK:", req.body.type, req.body.content); 8 | next(); 9 | } 10 | -------------------------------------------------------------------------------- /clients/kotlin/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Jan 19 15:05:17 CET 2020 2 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-all.zip 3 | distributionBase=GRADLE_USER_HOME 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /clients/typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2017", 5 | "noImplicitAny": true, 6 | "outDir": "./dist", 7 | "sourceMap": true 8 | }, 9 | "include": [ 10 | "./src/**/*" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /clients/c#/coreWebApi/NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /clients/c#/dnx-csharp/NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /clients/erlang/src/xcarpaccio.erl: -------------------------------------------------------------------------------- 1 | -module(xcarpaccio). 2 | 3 | -export([start/0]). 4 | 5 | start() -> 6 | ok = application:start(crypto), 7 | ok = application:start(ranch), 8 | ok = application:start(cowlib), 9 | ok = application:start(cowboy), 10 | ok = application:start(xcarpaccio). 11 | -------------------------------------------------------------------------------- /clients/java/java-httpserver/src/main/java/xcarpaccio/Result.java: -------------------------------------------------------------------------------- 1 | package xcarpaccio; 2 | 3 | public class Result { 4 | public Double total; 5 | 6 | public Result() { // Empty constructor required by Jackson 7 | } 8 | 9 | public Result(Double total) { 10 | this.total = total; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /clients/groovy/groovy-ratpack/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Mar 13 14:31:38 CET 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-bin.zip 7 | -------------------------------------------------------------------------------- /clients/racket/carpaccio.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (provide carpaccio/total) 4 | 5 | (define (carpaccio/total details country reduction) 6 | 0.0) 7 | 8 | 9 | (module+ test 10 | 11 | (require rackunit rackunit/text-ui) 12 | 13 | (check-equal? 0.0 (carpaccio/total '() "" "")) 14 | 15 | "all test run") -------------------------------------------------------------------------------- /clients/java/java-fluent-http/src/main/java/xcarpaccio/Logger.java: -------------------------------------------------------------------------------- 1 | package xcarpaccio; 2 | 3 | public class Logger { 4 | 5 | public void log(String message) { 6 | System.out.println(message); 7 | } 8 | 9 | public void error(String message) { 10 | System.err.println(message); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /clients/typescript/src/calc.spec.ts: -------------------------------------------------------------------------------- 1 | import { sayHello } from "./calc"; 2 | 3 | 4 | describe("Test calc", () => { 5 | 6 | test("Example unit test", () => { 7 | expect(true).toBe(true); 8 | }); 9 | 10 | it("say hello", () => { 11 | expect(sayHello()).toBe("Hello World"); 12 | }) 13 | 14 | }) -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/app/views/layouts/mailer.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | <%= yield %> 12 | 13 | 14 | -------------------------------------------------------------------------------- /clients/scala/project/Dependencies.scala: -------------------------------------------------------------------------------- 1 | import sbt._ 2 | 3 | object Dependencies { 4 | lazy val `akka-http`: ModuleID = "com.typesafe.akka" %% "akka-http" % "10.0.9" 5 | lazy val `akka-http-circe`: ModuleID = "de.heikoseeberger" %% "akka-http-circe" % "1.16.1" 6 | lazy val `circe-generic`: ModuleID = "io.circe" %% "circe-generic" % "0.8.0" 7 | } 8 | -------------------------------------------------------------------------------- /clients/c#/dnx-csharp/src/xcarpaccio/models.cs: -------------------------------------------------------------------------------- 1 | namespace XCarpaccio 2 | { 3 | public class Feedback 4 | { 5 | public string Type { get; set; } 6 | public string Content { get; set; } 7 | 8 | public override string ToString() 9 | { 10 | return $"[{Type}] {Content}"; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /clients/kotlin/src/main/kotlin/xcarpaccio/Logger.kt: -------------------------------------------------------------------------------- 1 | package xcarpaccio 2 | 3 | class Logger { 4 | fun log(message: String) { 5 | println(message) 6 | } 7 | 8 | fun log(ex: Exception) { 9 | ex.printStackTrace() 10 | } 11 | 12 | fun error(message: String) { 13 | System.err.println(message) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /clients/php/silex/tests/functionals/features/Ping.feature: -------------------------------------------------------------------------------- 1 | Feature: Registration validation 2 | In order to play 3 | As a user 4 | I must confirm my registration 5 | 6 | Scenario: Registration confirmation 7 | Given I am a pre-registered user 8 | When I receive the registration validation 9 | Then I must validate my registration 10 | -------------------------------------------------------------------------------- /clients/erlang/src/xcarpaccio.app.src: -------------------------------------------------------------------------------- 1 | {application, xcarpaccio, 2 | [ 3 | {description, ""}, 4 | {vsn, "1"}, 5 | {registered, []}, 6 | {applications, [ 7 | kernel, 8 | stdlib, 9 | cowboy 10 | ]}, 11 | {mod, { xcarpaccio_app, []}}, 12 | {env, [{http_port, 1337}]} 13 | ]}. 14 | -------------------------------------------------------------------------------- /clients/php/silex/README.md: -------------------------------------------------------------------------------- 1 | Configure your /etc/hosts file with your docker IP address. The project hostname is "project.loc" 2 | 3 | Start docker environment : 4 | 5 | $ make start 6 | 7 | Stop docker environment : 8 | 9 | $ make stop 10 | 11 | Start provisioning : 12 | 13 | $ make up 14 | 15 | Run tests : 16 | 17 | $ make tests 18 | -------------------------------------------------------------------------------- /clients/c#/nancy/NancyApplication1/IndexModule.cs: -------------------------------------------------------------------------------- 1 | namespace NancyApplication1 2 | { 3 | using Nancy; 4 | 5 | public class IndexModule : NancyModule 6 | { 7 | public IndexModule() 8 | { 9 | Get["/"] = parameters => 10 | { 11 | return View["index"]; 12 | }; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /clients/php/socket/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "extremeCarpaccioPhpClient", 3 | "minimum-stability": "stable", 4 | "license": "open source", 5 | "require": { 6 | "phpunit/phpunit": "6.5.14", 7 | "ext-sockets": "*", 8 | "ext-json": "*" 9 | }, 10 | "autoload": { 11 | "psr-0": { 12 | "" : "src" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /clients/c#/coreWebApi/src/xcarpaccio/Models/Feedback.cs: -------------------------------------------------------------------------------- 1 | namespace XCarpaccio.Models 2 | { 3 | public class Feedback 4 | { 5 | public string Type { get; set; } 6 | public string Content { get; set; } 7 | 8 | public override string ToString() 9 | { 10 | return $"[{Type}] {Content}"; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /clients/c#/nancy/extreme-carpaccio.client/Order.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace xCarpaccio.client 4 | { 5 | class Order 6 | { 7 | public decimal[] prices { get; set; } 8 | public int [] quantities { get; set; } 9 | public string country { get; set; } 10 | public string reduction { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /clients/rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "extreme" 3 | version = "0.1.0" 4 | authors = ["Jean-Eudes"] 5 | 6 | [dependencies] 7 | rustc-serialize = "0.3" 8 | 9 | [dependencies.nickel] 10 | version = "*" 11 | # If you are using the 'nightly' rust channel you can uncomment 12 | # the line below to activate unstable features 13 | # features = ["unstable"] 14 | 15 | -------------------------------------------------------------------------------- /clients/d/.gitignore: -------------------------------------------------------------------------------- 1 | .dub 2 | docs.json 3 | __dummy.html 4 | docs/ 5 | /extreme-carpaccio-server 6 | extreme-carpaccio-server.so 7 | extreme-carpaccio-server.dylib 8 | extreme-carpaccio-server.dll 9 | extreme-carpaccio-server.a 10 | extreme-carpaccio-server.lib 11 | extreme-carpaccio-server-test-* 12 | *.exe 13 | *.o 14 | *.obj 15 | *.lst 16 | *.dll 17 | dub.selections.json 18 | -------------------------------------------------------------------------------- /clients/javascript/node-plain/README.md: -------------------------------------------------------------------------------- 1 | # Run 2 | 3 | ``` 4 | npm start 5 | ``` 6 | 7 | # Test 8 | 9 | ``` 10 | npm test 11 | ``` 12 | 13 | # Resources 14 | 15 | * [Simplified HTTP request client](https://github.com/request/request) 16 | * [Using Jasmine-Node to Test Your Node Server](http://randomjavascript.blogspot.fr/2012/12/using-jasmine-node-to-test-your-node.html) 17 | -------------------------------------------------------------------------------- /clients/php/silex/tests/functionals/features/bootstrap/ExtremeCarpaccio/FeatureContext.php: -------------------------------------------------------------------------------- 1 | 2000) return price * 1.18; else return price * 1.18; }" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/server" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | versioning-strategy: increase-if-necessary 9 | ignore: 10 | - dependency-name: chalk 11 | - dependency-name: eslint-plugin-promise 12 | versions: 13 | - 4.3.0 14 | commit-message: 15 | prefix: "chore" 16 | -------------------------------------------------------------------------------- /clients/erlang/rebar.config: -------------------------------------------------------------------------------- 1 | %% -*- erlang -*- 2 | {erl_opts, [debug_info]}. 3 | {deps, [ 4 | {cowboy, "1.0.1", {git, "https://github.com/ninenines/cowboy.git", {tag, "1.0.1"}}}, 5 | {jsx, "2.4.0", {git, "https://github.com/talentdeficit/jsx.git", {tag, "v2.4.0"}}} 6 | ]}. 7 | {cover_enabled, true}. 8 | {eunit_opts, [ 9 | verbose, {report,{eunit_surefire,[{dir,"."}]}} 10 | ]}. 11 | -------------------------------------------------------------------------------- /clients/php/native/docker/php/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:fpm 2 | 3 | WORKDIR /home/project 4 | 5 | RUN apt-get update && apt-get upgrade -y && apt-get install -y git libssl-dev wget && \ 6 | docker-php-ext-install zip mbstring && \ 7 | pecl install xdebug-beta && docker-php-ext-enable xdebug 8 | 9 | RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer 10 | -------------------------------------------------------------------------------- /clients/php/silex/docker/php/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:fpm 2 | 3 | WORKDIR /home/project 4 | 5 | RUN apt-get update && apt-get upgrade -y && apt-get install -y git libssl-dev wget && \ 6 | docker-php-ext-install zip mbstring && \ 7 | pecl install xdebug-beta && docker-php-ext-enable xdebug 8 | 9 | RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer 10 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/README.md: -------------------------------------------------------------------------------- 1 | ## Dependencies 2 | - Ruby v2.0+ 3 | - Ruby gem 4 | 5 | ## Install 6 | ``` 7 | gem install bundler 8 | bundle install 9 | ``` 10 | 11 | ## Start 12 | ``` 13 | bundle exec rails s -p8888 -b0.0.0.0 14 | # -b0.0.0.0 Is to allow access from LAN or else only localhost can access 15 | ``` 16 | 17 | The server listens on port 8888: [http://localhost:8888](http://localhot:8888) 18 | -------------------------------------------------------------------------------- /clients/haskell/test/Spec.hs: -------------------------------------------------------------------------------- 1 | module Main where 2 | 3 | import Test.Hspec 4 | import Model 5 | 6 | main :: IO () 7 | main = hspec $ do 8 | 9 | describe "computeTotal" $ do 10 | 11 | -- Replace this test with a relevant ones 12 | it "should give the dummy value of 1000" $ do 13 | let order = Order [3.14] [42] "WHATEVER" "WHATEVER" 14 | in computeTotal order `shouldBe` Quantity 1000.0 15 | -------------------------------------------------------------------------------- /clients/java/java-httpserver/src/main/java/xcarpaccio/Logger.java: -------------------------------------------------------------------------------- 1 | package xcarpaccio; 2 | 3 | public class Logger { 4 | public void log(String message) { 5 | System.out.println(message); 6 | } 7 | 8 | public void log(Exception ex) { 9 | ex.printStackTrace(); 10 | } 11 | 12 | public void error(String message) { 13 | System.err.println(message); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.iml 3 | 4 | lib-cov 5 | *.seed 6 | *.log 7 | *.csv 8 | *.dat 9 | *.out 10 | *.pid 11 | *.gz 12 | *.orig 13 | 14 | [Dd]ebug/ 15 | [Oo]bj/ 16 | [Bb]in 17 | [Rr]elease 18 | *.suo 19 | **/packages/* 20 | pids 21 | logs 22 | results 23 | 24 | npm-debug.log 25 | node_modules 26 | 27 | server/public/components 28 | *.sublime-project 29 | *.sublime-workspace 30 | .DS_Store 31 | *.tmp 32 | *.swp 33 | -------------------------------------------------------------------------------- /clients/php/socket/tests/TestOrder.php: -------------------------------------------------------------------------------- 1 | assertEquals($expected, $actual); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/db/seeds.rb: -------------------------------------------------------------------------------- 1 | # This file should contain all the record creation needed to seed the database with its default values. 2 | # The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). 3 | # 4 | # Examples: 5 | # 6 | # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) 7 | # Character.create(name: 'Luke', movie: movies.first) 8 | -------------------------------------------------------------------------------- /clients/javascript/node-plain/lib/logic.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Where all the logic should be executed (http entry point) 3 | * 4 | * @param {Object} reqBody - http request body payload 5 | * @return {Object} response that will be returned as json 6 | * @api public 7 | */ 8 | var applyLogic = function(reqBody) { 9 | 10 | // TODO implement from here 11 | return {total: 0.0}; 12 | }; 13 | 14 | module.exports = applyLogic; 15 | -------------------------------------------------------------------------------- /clients/python/simple-server/README.md: -------------------------------------------------------------------------------- 1 | # Python Client server 2 | 3 | The server is developed with python 3.4 4 | 5 | ## How to run the server 6 | 7 | ### Console 8 | You can run it with python console 9 | 10 | ``` 11 | import client 12 | client.start_server() 13 | ``` 14 | 15 | ### Python call 16 | Calling python . in the project directory 17 | 18 | ``` 19 | python . 20 | ``` 21 | 22 | Or use your favorite IDE 23 | -------------------------------------------------------------------------------- /clients/c#/dnx-csharp/test/xcarpaccio.tests/tests.cs: -------------------------------------------------------------------------------- 1 | namespace XCarpaccio.Tests 2 | { 3 | using Xunit; 4 | 5 | public class WalkingSkeleton 6 | { 7 | [Fact] 8 | public void feedback_model_prints_nicely() 9 | { 10 | var feedback = new Feedback() { Type = "Error", Content = "Hello" }; 11 | Assert.Equal("[Error] Hello", feedback.ToString()); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /clients/php/native/tests/functionals/casperjs/02-ping.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | casper.test.begin('Check http://project.loc/ping', 2, function(test) { 4 | casper.start('http://project.loc/ping', function() { 5 | test.assertHttpStatus(200); 6 | }).then(function() { 7 | test.assertEquals(this.getPageContent(), 'pong', "Pong found"); 8 | }).run(function() { 9 | test.done(); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /clients/php/silex/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | web: 5 | image: nginx:latest 6 | ports: 7 | - "80:80" 8 | volumes: 9 | - .:/home/project 10 | - ./docker/nginx/site.conf:/etc/nginx/conf.d/site.conf 11 | 12 | php: 13 | build: ./docker/php 14 | volumes: 15 | - .:/home/project 16 | working_dir: /home/project 17 | links: 18 | - "web:project.loc" 19 | -------------------------------------------------------------------------------- /clients/python/simple-server-python3/README.md: -------------------------------------------------------------------------------- 1 | # Python Client server 2 | 3 | The server is developed with python 3.4 4 | 5 | ## How to run the server 6 | 7 | ### Console 8 | You can run it with python console 9 | 10 | ``` 11 | import client 12 | client.start_server() 13 | ``` 14 | 15 | ### Python call 16 | Calling python . in the project directory 17 | 18 | ``` 19 | python . 20 | ``` 21 | 22 | Or use your favorite IDE 23 | -------------------------------------------------------------------------------- /clients/c#/nancy/NancyApplication1/Bootstrapper.cs: -------------------------------------------------------------------------------- 1 | namespace NancyApplication1 2 | { 3 | using Nancy; 4 | 5 | public class Bootstrapper : DefaultNancyBootstrapper 6 | { 7 | // The bootstrapper enables you to reconfigure the composition of the framework, 8 | // by overriding the various methods and properties. 9 | // For more information https://github.com/NancyFx/Nancy/wiki/Bootstrapper 10 | } 11 | } -------------------------------------------------------------------------------- /clients/f#/carpaccio-client/carpaccio-model.fs: -------------------------------------------------------------------------------- 1 | module CarpaccioModel 2 | open System 3 | 4 | [] 5 | type Result = {total: double} 6 | 7 | [] 8 | type Feedback = 9 | { Type: string 10 | Content: string } 11 | 12 | [] 13 | type Order = 14 | { prices : double[] 15 | quantities: double[] 16 | country: string 17 | reduction: string 18 | } 19 | -------------------------------------------------------------------------------- /clients/java/java-springboot/src/main/java/xcarpaccio/CarpaccioApplication.java: -------------------------------------------------------------------------------- 1 | package xcarpaccio; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CarpaccioApplication { 8 | public static void main(String[] args) { 9 | SpringApplication.run(CarpaccioApplication.class, args); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /clients/javascript/express/test/200-process-order.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var process = require('../lib/process'); 3 | 4 | describe('process.order(payload, callback)', function () { 5 | it('calls back with an empty object', function (done) { 6 | process.order({}, function (err, result) { 7 | if (err) return done(err); 8 | expect(result).to.deep.equal({}); 9 | done(); 10 | }) 11 | }) 12 | }) 13 | -------------------------------------------------------------------------------- /clients/javascript/node-plain/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "extreme-carpaccio-client-node-plain", 3 | "version": "0.1.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node main.js", 7 | "test": "./node_modules/jasmine-node/bin/jasmine-node ." 8 | }, 9 | "dependencies": { 10 | "request": "2.53.*", 11 | "chalk": "^1.1.3" 12 | }, 13 | "devDependencies": { 14 | "jasmine-node": "^1.14.5" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /clients/php/native/web/app.php: -------------------------------------------------------------------------------- 1 | function () { 9 | header('HTTP/1.1 204 No Content'); 10 | header('Content-Type: text/plain; charset=utf8'); 11 | }, 12 | ]; 13 | 14 | $route = in_array($_SERVER['REQUEST_URI'], ['/', '/ping', ]) ? $_SERVER['REQUEST_URI'] : '/'; 15 | 16 | $actions[$route](); 17 | -------------------------------------------------------------------------------- /clients/c#/nancy/extreme-carpaccio.client/Bootstrapper.cs: -------------------------------------------------------------------------------- 1 | namespace xCarpaccio.client 2 | { 3 | using Nancy; 4 | 5 | public class Bootstrapper : DefaultNancyBootstrapper 6 | { 7 | // The bootstrapper enables you to reconfigure the composition of the framework, 8 | // by overriding the various methods and properties. 9 | // For more information https://github.com/NancyFx/Nancy/wiki/Bootstrapper 10 | } 11 | } -------------------------------------------------------------------------------- /.github/workflows/on-all-prs.yml: -------------------------------------------------------------------------------- 1 | on: pull_request 2 | 3 | permissions: 4 | contents: write 5 | pull-requests: write 6 | 7 | jobs: 8 | automerge-when-author-is-dependabot: 9 | runs-on: ubuntu-latest 10 | if: github.actor == 'dependabot[bot]' 11 | steps: 12 | - run: gh pr merge --auto --merge "$PR_URL" 13 | env: 14 | PR_URL: ${{github.event.pull_request.html_url}} 15 | GH_TOKEN: ${{secrets.GITHUB_TOKEN}} 16 | 17 | -------------------------------------------------------------------------------- /clients/haskell/src/Model.hs: -------------------------------------------------------------------------------- 1 | module Model 2 | where 3 | 4 | data Order = Order 5 | { prices :: [Double] 6 | , quantities :: [Integer] 7 | , country :: String 8 | , reduction :: String 9 | } deriving (Show) 10 | 11 | data Quantity = Quantity 12 | { _total :: Double } deriving (Show,Eq) 13 | 14 | computeTotal :: Order -> Quantity 15 | computeTotal _ = 16 | -- You should replace this dummy value with your algorithm 17 | Quantity 1000.0 18 | -------------------------------------------------------------------------------- /clients/ruby/sinatra/README.md: -------------------------------------------------------------------------------- 1 | A ruby client based on [http://www.sinatrarb.com/](Sinatra) 2 | 3 | ## Dependencies 4 | - Ruby v2.0+ 5 | - Ruby gem 6 | 7 | ## Install 8 | ``` 9 | gem install sinatra sinatra-reloader json rack-test 10 | ``` 11 | 12 | ## Start 13 | ``` 14 | ruby lib/extreme-carpaccio.rb 15 | ``` 16 | 17 | The server listens on port 9000: (http://localhost:4567/ping)[http://localhot:4567] 18 | 19 | ## Test 20 | 21 | ``` 22 | rake test 23 | ``` 24 | -------------------------------------------------------------------------------- /clients/c#/nancy/NancyApplication1/Views/index.sshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NancyApplication1 6 | 7 | 14 | 15 | 16 | 17 | Nancy logo
18 | This view was rendered using the SuperSimpleViewEngine 19 | 20 | 21 | -------------------------------------------------------------------------------- /clients/java/java-springboot/src/main/java/xcarpaccio/FeedbackMessage.java: -------------------------------------------------------------------------------- 1 | package xcarpaccio; 2 | 3 | public class FeedbackMessage { 4 | public String type; 5 | public String content; 6 | 7 | @Override 8 | public String toString() { 9 | return "FeedbackMessage{" + 10 | "type='" + type + '\'' + 11 | ", content='" + content + '\'' + 12 | '}'; 13 | } 14 | 15 | public FeedbackMessage() { 16 | } 17 | } -------------------------------------------------------------------------------- /clients/php/native/docker-compose.yml: -------------------------------------------------------------------------------- 1 | php: 2 | build: docker/php 3 | volumes: 4 | - .:/home/project 5 | working_dir: /home/project 6 | 7 | web: 8 | image: nginx:latest 9 | ports: 10 | - "80:80" 11 | volumes: 12 | - .:/home/project 13 | - ./docker/nginx/site.conf:/etc/nginx/conf.d/site.conf 14 | links: 15 | - php 16 | 17 | testing: 18 | image: vitr/casperjs 19 | volumes: 20 | - .:/home/project 21 | links: 22 | - "web:project.loc" 23 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /clients/php/native/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "extreme-carpaccio/clients-php-native", 3 | "autoload": { 4 | "psr-4": { 5 | "ExtremeCarpaccio\\": "src/ExtremeCarpaccio" 6 | } 7 | }, 8 | "require-dev": { 9 | "atoum/atoum": "~3.0", 10 | "atoum/stubs": "~2.5" 11 | }, 12 | "autoload-dev": { 13 | "psr-4": { 14 | "Tests\\Units\\": "tests/units", 15 | "Tests\\Units\\ExtremeCarpaccio\\": "tests/units/src/ExtremeCarpaccio" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /clients/c#/coreWebApi/src/xcarpaccio/Controllers/OrderController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using XCarpaccio.Models; 3 | 4 | namespace XCarpaccio.Controllers 5 | { 6 | [Route("[controller]")] 7 | public class OrderController : Controller 8 | { 9 | public OrderController(){ 10 | } 11 | 12 | [HttpPost] 13 | public IActionResult Post([FromBody]Order order) 14 | { 15 | return this.NotFound(); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /clients/c#/coreWebApi/test/xcarpaccio.tests/feedbackTest.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using Xunit; 3 | using XCarpaccio.Models; 4 | 5 | namespace XCarpaccio.Tests 6 | { 7 | 8 | public class WalkingSkeleton 9 | { 10 | [Fact] 11 | public void feedback_model_prints_nicely() 12 | { 13 | var feedback = new Feedback() { Type = "Error", Content = "Hello" }; 14 | Assert.Equal("[Error] Hello", feedback.ToString()); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /clients/php/silex/tests/functionals/features/Order.feature: -------------------------------------------------------------------------------- 1 | Feature: Order management 2 | In order to calculate the bill 3 | I must compute the amount of the received orders 4 | 5 | Scenario: Order without reduction 6 | Given I have the following order 7 | | price | quantity | 8 | | 15.99 | 1 | 9 | And the country is "ES" 10 | And the reduction is "STANDARD" 11 | When I validate 12 | Then The total must be 19.03 € 13 | -------------------------------------------------------------------------------- /clients/javascript/express/README.md: -------------------------------------------------------------------------------- 1 | Express Client 2 | ============== 3 | 4 | Install 5 | ------- 6 | 7 | npm install 8 | 9 | Start 10 | ----- 11 | 12 | PORT=1234 npm start 13 | 14 | default port is 3000 15 | 16 | Start with ` nodemon ` 17 | _(Alternatively, you can use nodemon instead of node.)_ 18 | ----- 19 | 20 | npm run nodemon 21 | > about nodemon: http://nodemon.io/ 22 | 23 | Test 24 | ---- 25 | 26 | npm test 27 | 28 | Implement 29 | ---- 30 | See TODO in `routes.js` 31 | -------------------------------------------------------------------------------- /server/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bower.json", 3 | "version": "0.0.0", 4 | "authors": [ 5 | "dotnetstation " 6 | ], 7 | "description": "bower packages", 8 | "dependencies": { 9 | "react": "~0.12.2", 10 | "bootstrap": "~3.3.2", 11 | "react-bootstrap": "~0.15.1", 12 | "respond": "~1.4.2", 13 | "html5shiv": "~3.7.2", 14 | "jquery": "~2.1.3", 15 | "react-intl": "~1.1.0", 16 | "chartjs": "~1.0.1", 17 | "lodash": "~3.4.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /clients/php/native/README.md: -------------------------------------------------------------------------------- 1 | Configure your /etc/hosts file with your docker IP address. The project hostname is "project.loc" 2 | 3 | Start docker environment : 4 | 5 | $ make start 6 | 7 | Stop docker environment : 8 | 9 | $ make stop 10 | 11 | Start provisioning : 12 | 13 | $ make up 14 | 15 | Run functional tests : 16 | 17 | $ make functional-tests 18 | 19 | Run unit tests : 20 | 21 | $ make unit-tests 22 | 23 | Run all tests : 24 | 25 | $ make tests 26 | 27 | -------------------------------------------------------------------------------- /clients/php/socket/src/FeedbackMessage.php: -------------------------------------------------------------------------------- 1 | _type = $type; 11 | $this->_content = $content; 12 | } 13 | 14 | public function GetMessage(): string 15 | { 16 | return $this->_content; 17 | } 18 | 19 | public function GetType() 20 | { 21 | return $this->_type; 22 | } 23 | } -------------------------------------------------------------------------------- /clients/java/java-fluent-http/src/main/java/xcarpaccio/MyFluentHttpServer.java: -------------------------------------------------------------------------------- 1 | package xcarpaccio; 2 | 3 | import net.codestory.http.WebServer; 4 | 5 | public class MyFluentHttpServer { 6 | 7 | public MyFluentHttpServer() { 8 | this(9000); 9 | } 10 | 11 | public MyFluentHttpServer(int port) { 12 | new WebServer().configure(new WebConfiguration()).start(port); 13 | } 14 | 15 | public static void main( String[] args ) { 16 | new MyFluentHttpServer(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /clients/php/silex/tests/functionals/features/bootstrap/ExtremeCarpaccio/ApiContext.php: -------------------------------------------------------------------------------- 1 | baseUrl = $baseUrl; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /clients/java/java-spark/src/main/java/extremecarpaccio/JsonResponseTransformer.java: -------------------------------------------------------------------------------- 1 | package extremecarpaccio; 2 | 3 | import com.google.gson.Gson; 4 | import spark.ResponseTransformer; 5 | 6 | public class JsonResponseTransformer implements ResponseTransformer { 7 | private final Gson gson; 8 | 9 | public JsonResponseTransformer(Gson gson) { 10 | this.gson = gson; 11 | } 12 | 13 | @Override 14 | public String render(Object o) throws Exception { 15 | return gson.toJson(o); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /clients/php/socket/src/JsonFeedbackMapper.php: -------------------------------------------------------------------------------- 1 | 12 | { 13 | WriteLine($"[{ctx.Request.Method}] {ctx.Request.Path}"); 14 | return next(); 15 | }); 16 | app.UseOwin(x => x.UseNancy()); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /server/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true, 5 | "node": true 6 | }, 7 | "extends": [ 8 | "standard" 9 | ], 10 | "globals": { 11 | "Atomics": "readonly", 12 | "SharedArrayBuffer": "readonly" 13 | }, 14 | "parserOptions": { 15 | "ecmaFeatures": { 16 | "jsx": true 17 | }, 18 | "ecmaVersion": 2018, 19 | "sourceType": "module" 20 | }, 21 | "plugins": [ 22 | "react" 23 | ], 24 | "rules": { 25 | } 26 | } -------------------------------------------------------------------------------- /server/specs/investigating_spec.js: -------------------------------------------------------------------------------- 1 | 2 | describe('Configuration', function(){ 3 | it('should evaluate function from string', function() { 4 | var customEval = function(s) { return new Function("return " + s)(); }, 5 | str1 = "function (price) { return price - 50; }", 6 | fun1 = customEval(str1), 7 | str2 = "function (price) { return price / 2; }", 8 | fun2 = customEval(str2); 9 | 10 | expect(fun1.apply(null, [124])).toEqual(74); 11 | expect(fun2.apply(null, [124])).toEqual(62); 12 | }) 13 | }); -------------------------------------------------------------------------------- /clients/c#/dnx-csharp/build.sh: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo =============================== 3 | echo - Xtrem Carpaccio! - 4 | echo =============================== 5 | 6 | echo ======== RESTORE DEPENDENCIES ============= 7 | dnu commands install Microsoft.Dnx.Watcher 8 | dnu restore 9 | 10 | echo ======== BUILD SOURCES ============= 11 | cd src/xcarpaccio/ 12 | dnu build 13 | cd ../.. 14 | echo ======== BUILD TESTS ============= 15 | cd test/xcarpaccio.tests/ 16 | dnu build 17 | echo ======== RUN TESTS ============= 18 | dnx test 19 | cd ../../ 20 | -------------------------------------------------------------------------------- /.github/workflows/on-prs-made-against-the-server.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - server/** 7 | 8 | jobs: 9 | run-tests-on-windows: 10 | name: on windows 11 | runs-on: windows-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | - run: npm install && npm test 15 | working-directory: server 16 | run-tests-on-linux: 17 | name: on linux 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: actions/checkout@v3 21 | - run: npm install && npm test 22 | working-directory: server 23 | -------------------------------------------------------------------------------- /clients/c#/dnx-csharp/src/xcarpaccio/app.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using Microsoft.AspNetCore.Builder; 3 | using Microsoft.AspNetCore.Hosting; 4 | 5 | namespace XCarpaccio 6 | { 7 | 8 | public class Program 9 | { 10 | public static void Main(params string[] args) 11 | { 12 | var host = new WebHostBuilder() 13 | .UseContentRoot(Directory.GetCurrentDirectory()) 14 | .UseKestrel() 15 | .UseStartup() 16 | .Build(); 17 | 18 | host.Run(); 19 | } 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /clients/f#/README.md: -------------------------------------------------------------------------------- 1 | Suave is a simple web development F# library providing a lightweight web server and a set of combinators to manipulate route flow and task composition. 2 | 3 | This project has been created with Fsharp yeoman [generator](https://github.com/fsprojects/generator-fsharp). 4 | It uses [Fake](http://fsharp.github.io/FAKE/) and [Paket](https://fsprojects.github.io/Paket/). 5 | 6 | 7 | It can now run without Visual studio as well and on other platform using Mono. 8 | 9 | You just need to run build.sh or build.cmd depending on your platform. 10 | 11 | Good luck ! -------------------------------------------------------------------------------- /clients/clojure/test/extremecarpaccio/core_test.clj: -------------------------------------------------------------------------------- 1 | (ns extremecarpaccio.core-test 2 | (:require [midje.sweet :refer :all] 3 | [ring.mock.request :as mock] 4 | [extremecarpaccio.core :refer :all])) 5 | 6 | (facts "about routes" 7 | (fact "ping route should respond pong" 8 | (let [response (my-app (mock/request :get "/ping"))] 9 | (:status response) => 200 10 | (:body response) => "pong")) 11 | 12 | (fact "not-found route should respond 404" 13 | (let [response (my-app (mock/request :get "/invalid"))] 14 | (:status response) => 404))) -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /clients/php/native/.bootstrap.atoum.php: -------------------------------------------------------------------------------- 1 | 10 | Vals = jsx:decode(<<"{\"prices\":[75.87],\"quantities\":[5],\"country\":\"FR\"}">>), 11 | Key = <<"prices">>, 12 | ?assertEqual({Key, [75.87]}, proplists:lookup(Key, Vals)). 13 | 14 | encoding_test() -> 15 | Data = #{total => 0.0}, 16 | Json = jsx:encode(Data), 17 | ?assertEqual(<<"{\"total\":0.0}">>, Json). 18 | -------------------------------------------------------------------------------- /clients/java/java-spark/src/main/java/extremecarpaccio/Strings.java: -------------------------------------------------------------------------------- 1 | package extremecarpaccio; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | 7 | public class Strings { 8 | 9 | public static String stringify(InputStream is, String charset) throws IOException { 10 | byte[] buffer = new byte[1024]; 11 | ByteArrayOutputStream bout = new ByteArrayOutputStream(); 12 | int read; 13 | while ((read = is.read(buffer)) >= 0) { 14 | bout.write(buffer, 0, read); 15 | } 16 | return bout.toString(charset); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /clients/c#/coreWebApi/src/xcarpaccio/web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /clients/python/flask-server/README.md: -------------------------------------------------------------------------------- 1 | #Flask python Client server 2 | 3 | The server is developed with Flask (http://flask.pocoo.org/). 4 | To run the test you need at least python 2.7.8. 5 | 6 | ## How to Install 7 | ``` 8 | pip install Flask 9 | ``` 10 | 11 | ## How to run the server 12 | 13 | The server runs by defaut on port 5000 and listens to any open interface. 14 | 15 | ### Console 16 | You can run it with python console : 17 | 18 | ``` 19 | import client 20 | client.start_server() 21 | ``` 22 | 23 | ### Python call 24 | Calling python . in the project directory : 25 | 26 | ``` 27 | python . 28 | ``` 29 | 30 | Or use your favorite IDE. 31 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | 10 | # Ignore the default SQLite database. 11 | /db/*.sqlite3 12 | /db/*.sqlite3-journal 13 | 14 | # Ignore all logfiles and tempfiles. 15 | /log/* 16 | /tmp/* 17 | !/log/.keep 18 | !/tmp/.keep 19 | 20 | # Ignore Byebug command history file. 21 | .byebug_history 22 | -------------------------------------------------------------------------------- /clients/c#/dnx-csharp/test/xcarpaccio.tests/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | "buildOptions": { 4 | "debugType": "portable" 5 | }, 6 | "dependencies": { 7 | "xunit": "2.1.0", 8 | "dotnet-test-xunit": "2.2.0-preview2-build1029", 9 | "xcarpaccio": { "target": "project" } 10 | }, 11 | "testRunner": "xunit", 12 | "frameworks": { 13 | "netcoreapp1.0": { 14 | "dependencies": { 15 | "Microsoft.NETCore.App": { 16 | "type": "platform", 17 | "version": "1.0.0" 18 | } 19 | }, 20 | "imports": [ 21 | "dotnet5.4", 22 | "portable-net451+win8" 23 | ] 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /clients/javascript/express/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "carpaccio-client-express", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "mocha test", 8 | "nodemon": "nodemon server.js" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "chai": "^3.4.1", 14 | "mocha": "^2.3.4", 15 | "nodemon": "^1.17.3", 16 | "sinon": "^1.17.2", 17 | "sinon-chai": "^2.8.0", 18 | "supertest": "^1.1.0" 19 | }, 20 | "dependencies": { 21 | "body-parser": "^1.14.1", 22 | "express": "^4.13.3", 23 | "morgan": "^1.6.1", 24 | "request": "^2.67.0" 25 | } 26 | } -------------------------------------------------------------------------------- /clients/racket/README.md: -------------------------------------------------------------------------------- 1 | # Extreme Carpaccio Racket starting code 2 | 3 | ## Prerequisites 4 | 5 | You will need [Racket](http://racket-lang.org/) installed. 6 | 7 | ## Test Driven Development 8 | 9 | 1. Lauch DrRacket 10 | 2. Load file ```carpaccio.rkt ``` 11 | 3. Run it with ```Ctrl-R``` 12 | 4. Check tests are ok with message ```all test run``` 13 | 14 | You can start your TDD loops. 15 | 16 | ## Running in "production" 17 | 18 | To start a web server for the application, run: 19 | 20 | $ racket -tm web-server.rkt 21 | 22 | You can save the output in a log file with the ```tee``` command: 23 | 24 | $ racket -tm web-server.rkt | tee -a log.txt 25 | 26 | -------------------------------------------------------------------------------- /clients/c#/coreWebApi/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "command": "dotnet", 4 | "isShellCommand": true, 5 | "args": [], 6 | "tasks": [ 7 | { 8 | "taskName": "build", 9 | "args": [ 10 | "${workspaceRoot}\\src\\xcarpaccio\\project.json" 11 | ], 12 | "isBuildCommand": true, 13 | "problemMatcher": "$msCompile" 14 | }, 15 | { 16 | "taskName": "test", 17 | "args": [ 18 | "${workspaceRoot}\\test\\xcarpaccio.tests\\project.json" 19 | ], 20 | "isTestCommand" : true 21 | } 22 | ] 23 | } -------------------------------------------------------------------------------- /clients/c#/dnx-csharp/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "command": "dotnet", 4 | "isShellCommand": true, 5 | "args": [], 6 | "tasks": [ 7 | { 8 | "taskName": "build", 9 | "args": [ 10 | "${workspaceRoot}\\src\\xcarpaccio\\project.json" 11 | ], 12 | "isBuildCommand": true, 13 | "problemMatcher": "$msCompile" 14 | }, 15 | { 16 | "taskName": "test", 17 | "args": [ 18 | "${workspaceRoot}\\test\\xcarpaccio.tests\\project.json" 19 | ], 20 | "isTestCommand" : true 21 | } 22 | ] 23 | } -------------------------------------------------------------------------------- /clients/c#/nancy/NancyApplication1/Program.cs: -------------------------------------------------------------------------------- 1 | namespace NancyApplication1 2 | { 3 | using System; 4 | using Nancy.Hosting.Self; 5 | 6 | class Program 7 | { 8 | static void Main(string[] args) 9 | { 10 | var uri = 11 | new Uri("http://localhost:3579"); 12 | 13 | using (var host = new NancyHost(uri)) 14 | { 15 | host.Start(); 16 | 17 | Console.WriteLine("Your application is running on " + uri); 18 | Console.WriteLine("Press any [Enter] to close the host."); 19 | Console.ReadLine(); 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /clients/clojure/project.clj: -------------------------------------------------------------------------------- 1 | (defproject extremecarpaccio "0.1.0-SNAPSHOT" 2 | :description "Dumbed down Clojure example code for Extreme Carpaccio kata" 3 | :url "https://github.com/dlresende/extreme-carpaccio" 4 | :min-lein-version "2.0.0" 5 | :dependencies [[org.clojure/clojure "1.10.0"] 6 | [compojure "1.6.1"] 7 | [ring "1.8.0"] 8 | [ring/ring-mock "0.4.0"] 9 | [ring-middleware-format "0.7.4"]] 10 | :plugins [[lein-ring "0.12.5"] 11 | [lein-midje "3.2.2"]] 12 | :ring {:handler extremecarpaccio.core/my-app} 13 | :profiles {:dev {:dependencies [[midje "1.9.9"]]}}) 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /clients/php/socket/src/Starter.php: -------------------------------------------------------------------------------- 1 | Start(); -------------------------------------------------------------------------------- /clients/groovy/groovy-ratpack/src/ratpack/Ratpack.groovy: -------------------------------------------------------------------------------- 1 | import static ratpack.groovy.Groovy.ratpack 2 | import groovy.json.JsonSlurper 3 | import groovy.util.logging.Slf4j; 4 | 5 | 6 | 7 | 8 | ratpack { 9 | handlers { 10 | 11 | get("hello") { 12 | render "Hello world!" 13 | } 14 | post("ping") { 15 | 16 | render "pong" 17 | } 18 | 19 | post("") { 20 | if (request.body.text) { 21 | def body = new JsonSlurper().parseText(request.body.text) 22 | println "Incoming request on '/': $body" 23 | } 24 | 25 | render "pong" 26 | } 27 | 28 | } 29 | } 30 | 31 | 32 | 33 | public String asJSON(total) { 34 | '{ "total": ' + total + ' }' 35 | } -------------------------------------------------------------------------------- /clients/java/java-fluent-http/README.md: -------------------------------------------------------------------------------- 1 | A Java client to with a simple net.codestory.http.WebServer implementation. 2 | 3 | ## Dependencies 4 | - maven 3 5 | - JDK 8 6 | 7 | ## Install 8 | - `mvn clean package` 9 | 10 | ## Run 11 | You don't need any application server. No Tomcat, no WAR to deploy. The server is embedded. 12 | 13 | - `mvn exec:java -Dexec.mainClass="xcarpaccio.MyFluentHttpServer"` 14 | 15 | The server listens on port 9000: [http://localhost:9000/ping](http://localhost:9000/ping) 16 | 17 | You can also launch the server with your IDE. You just have to launch `MyFluentHttpServer` class. It has a `main` method. 18 | 19 | The API is implemented in `WebConfiguration` class. 20 | -------------------------------------------------------------------------------- /clients/php/socket/tests/TestJsonFeedbackMapper.php: -------------------------------------------------------------------------------- 1 | setValues($json); 19 | 20 | $this->assertEquals($expectedFeedbackMessage, $feedbackMessage); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/config/database.yml: -------------------------------------------------------------------------------- 1 | # SQLite version 3.x 2 | # gem install sqlite3 3 | # 4 | # Ensure the SQLite 3 gem is defined in your Gemfile 5 | # gem 'sqlite3' 6 | # 7 | default: &default 8 | adapter: sqlite3 9 | pool: 5 10 | timeout: 5000 11 | 12 | development: 13 | <<: *default 14 | database: db/development.sqlite3 15 | 16 | # Warning: The database defined as "test" will be erased and 17 | # re-generated from your development database when you run "rake". 18 | # Do not set this db to the same as development or production. 19 | test: 20 | <<: *default 21 | database: db/test.sqlite3 22 | 23 | production: 24 | <<: *default 25 | database: db/production.sqlite3 26 | -------------------------------------------------------------------------------- /clients/typescript/src/server.ts: -------------------------------------------------------------------------------- 1 | import * as Koa from 'koa'; 2 | import * as Router from 'koa-router'; 3 | import bodyParser = require("koa-bodyparser"); 4 | import { sayHello } from './calc'; 5 | 6 | const app = new Koa(); 7 | app.use(bodyParser()); 8 | const router = new Router(); 9 | 10 | router.get('/*', async (ctx) => { 11 | ctx.body = sayHello(); 12 | }); 13 | 14 | router.post('/feedback', async (ctx) => { 15 | console.log('Feedback received', ctx.request.body); 16 | }); 17 | 18 | router.post('/order', async (ctx) => { 19 | // your code here 20 | }); 21 | 22 | app.use(router.routes()); 23 | 24 | app.listen(8080); 25 | 26 | console.log('Server running on port 8080'); 27 | 28 | -------------------------------------------------------------------------------- /clients/java/java-httpserver/src/main/java/xcarpaccio/Order.java: -------------------------------------------------------------------------------- 1 | package xcarpaccio; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Order { 6 | public Double[] prices; 7 | public Double[] quantities; 8 | public String country; 9 | public String reduction; 10 | 11 | @Override 12 | public String toString() { 13 | final StringBuilder sb = new StringBuilder("Order{"); 14 | sb.append("prices=").append(Arrays.toString(prices)); 15 | sb.append(", quantities=").append(Arrays.toString(quantities)); 16 | sb.append(", country='").append(country).append('\''); 17 | sb.append(", reduction='").append(reduction).append('\''); 18 | sb.append('}'); 19 | return sb.toString(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /clients/d/source/utils.d: -------------------------------------------------------------------------------- 1 | module utils; 2 | 3 | import vibe.d : HTTPStatus, HTTPStatusException; 4 | import std.stdio : writefln; 5 | 6 | /** 7 | * Displays a yellow message. 8 | */ 9 | void info(Args...)(string info, Args args) 10 | { 11 | writefln("\033[0;33m" ~ info ~ "\033[0m", args); 12 | } 13 | 14 | /** 15 | * Displays a red message. 16 | */ 17 | void error(Args...)(string error, Args args) 18 | { 19 | writefln("\033[1;31m" ~ error ~ "\033[0m", args); 20 | } 21 | 22 | /** 23 | * Throw an HTTP exception and returns the specified status code. 24 | */ 25 | void throwHTTPError(HTTPStatus status) 26 | { 27 | error("Sending HTTP code %d.", status); 28 | throw new HTTPStatusException(status); 29 | } -------------------------------------------------------------------------------- /clients/java/java-fluent-http/src/main/java/xcarpaccio/Message.java: -------------------------------------------------------------------------------- 1 | package xcarpaccio; 2 | 3 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 4 | import com.fasterxml.jackson.annotation.JsonCreator; 5 | import com.fasterxml.jackson.annotation.JsonProperty; 6 | 7 | @JsonAutoDetect( 8 | fieldVisibility = JsonAutoDetect.Visibility.ANY // mandatory for serialization 9 | ) 10 | public class Message { 11 | 12 | final String type; 13 | final String content; 14 | 15 | @JsonCreator 16 | public Message( 17 | @JsonProperty("type") String type, 18 | @JsonProperty("content") String content) { 19 | this.type = type; 20 | this.content = content; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /clients/java/java-springboot/src/main/java/xcarpaccio/Order.java: -------------------------------------------------------------------------------- 1 | package xcarpaccio; 2 | import java.io.Serializable; 3 | import java.util.Arrays; 4 | 5 | public class Order implements Serializable { 6 | public Double[] prices; 7 | public Long[] quantities; 8 | public String country; 9 | public String reduction; 10 | 11 | public Order() { 12 | } 13 | 14 | @Override 15 | public String toString() { 16 | return "Order{" + 17 | "prices=" + Arrays.toString(prices) + 18 | ", quantities=" + Arrays.toString(quantities) + 19 | ", country='" + country + '\'' + 20 | ", reduction='" + reduction + '\'' + 21 | '}'; 22 | } 23 | } -------------------------------------------------------------------------------- /clients/c#/nancy/extreme-carpaccio.client/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Threading; 3 | 4 | namespace xCarpaccio.client 5 | { 6 | using System; 7 | using Nancy.Hosting.Self; 8 | 9 | class Program 10 | { 11 | static void Main(string[] args) 12 | { 13 | var uri = 14 | new Uri("http://localhost:8080"); 15 | 16 | using (var host = new NancyHost(uri)) 17 | { 18 | host.Start(); 19 | 20 | Console.WriteLine("Your application is running on " + uri); 21 | Console.WriteLine("Press any [Enter] to close the host."); 22 | Console.ReadLine(); 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /clients/java/java-fluent-http/src/main/java/xcarpaccio/Order.java: -------------------------------------------------------------------------------- 1 | package xcarpaccio; 2 | 3 | import java.util.List; 4 | 5 | public class Order { 6 | public List prices; 7 | public List quantities; 8 | public List names; 9 | public String country; 10 | public String reduction; 11 | 12 | @Override 13 | public String toString() { 14 | final StringBuilder sb = new StringBuilder("Order{"); 15 | sb.append("prices=").append(prices); 16 | sb.append(", quantities=").append(quantities); 17 | sb.append(", names=").append(names); 18 | sb.append(", country='").append(country).append('\''); 19 | sb.append(", reduction='").append(reduction).append('\''); 20 | sb.append('}'); 21 | return sb.toString(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /clients/php/native/tests/units/src/ExtremeCarpaccio/Model/OrderProduct.php: -------------------------------------------------------------------------------- 1 | given( 13 | $unitPrice = mt_rand() / mt_rand(), 14 | $quantity = mt_rand() 15 | ) 16 | ->if( 17 | $this->newTestedInstance($unitPrice, $quantity) 18 | ) 19 | ->then 20 | ->integer($this->testedInstance->getQuantity())->isEqualTo($quantity) 21 | ->float($this->testedInstance->getUnitPrice())->isEqualTo($unitPrice) 22 | ; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /clients/php/silex/tests/units/src/ExtremeCarpaccio/Model/OrderProduct.php: -------------------------------------------------------------------------------- 1 | given( 13 | $unitPrice = mt_rand() / mt_rand(), 14 | $quantity = mt_rand() 15 | ) 16 | ->if( 17 | $this->newTestedInstance($unitPrice, $quantity) 18 | ) 19 | ->then 20 | ->integer($this->testedInstance->getQuantity())->isEqualTo($quantity) 21 | ->float($this->testedInstance->getUnitPrice())->isEqualTo($unitPrice) 22 | ; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym 'RESTful' 16 | # end 17 | -------------------------------------------------------------------------------- /clients/c#/dnx-csharp/src/xcarpaccio/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.0.1-*", 3 | "buildOptions": { 4 | "debugType": "portable", 5 | "emitEntryPoint": true 6 | }, 7 | "description":"my c# version of the extreme-carpaccio", 8 | "dependencies": { 9 | "Microsoft.NETCore.App": { 10 | "version": "1.0.0", 11 | "type": "platform" 12 | }, 13 | "Microsoft.AspNetCore.Server.Kestrel": "1.0.0", 14 | "Microsoft.AspNetCore.Owin": "1.0.0", 15 | "Nancy": "2.0.0-barneyrubble" 16 | }, 17 | "commands": { 18 | "web": "Microsoft.AspNet.Server.Kestrel --server.urls http://*:5000" 19 | }, 20 | "frameworks": { 21 | "netcoreapp1.0": {} 22 | }, 23 | "tooling": { 24 | "defaultNamespace": "XCarpaccio" 25 | } 26 | } 27 | 28 | 29 | -------------------------------------------------------------------------------- /clients/php/silex/behat.yml: -------------------------------------------------------------------------------- 1 | aliases: 2 | - &baseUrl http://project.loc 3 | 4 | default: 5 | extensions: 6 | Behat\MinkExtension: 7 | base_url: *baseUrl 8 | sessions: 9 | default: 10 | goutte: ~ 11 | suites: 12 | ping: 13 | paths: [%paths.base%/tests/functionals/features/Ping.feature] 14 | contexts: 15 | - 'Tests\Functionals\ExtremeCarpaccio\ApiContext\PingContext': 16 | - *baseUrl 17 | order: 18 | paths: [%paths.base%/tests/functionals/features/Order.feature] 19 | contexts: 20 | - 'Tests\Functionals\ExtremeCarpaccio\ApiContext\OrderContext': 21 | - *baseUrl 22 | -------------------------------------------------------------------------------- /clients/php/silex/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "extreme-carpaccio/clients-php-silex", 3 | "require": { 4 | "silex/silex": "~2.0", 5 | "monolog/monolog": "~1.22" 6 | }, 7 | "autoload": { 8 | "psr-4": { 9 | "ExtremeCarpaccio\\": "src/ExtremeCarpaccio" 10 | } 11 | }, 12 | "require-dev": { 13 | "atoum/atoum": "~3.0", 14 | "atoum/stubs": "~2.5", 15 | "behat/behat": "~3.3", 16 | "behat/mink-extension": "~2.2", 17 | "behat/mink-goutte-driver": "~1.0" 18 | }, 19 | "autoload-dev": { 20 | "psr-4": { 21 | "Tests\\Units\\": "tests/units", 22 | "Tests\\Units\\ExtremeCarpaccio\\": "tests/units/src/ExtremeCarpaccio", 23 | "Tests\\Functionals\\": "tests/functionals/features/bootstrap" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t 'hello' 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t('hello') %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # To learn more, please read the Rails Internationalization guide 20 | # available at http://guides.rubyonrails.org/i18n.html. 21 | 22 | en: 23 | hello: "Hello world" 24 | -------------------------------------------------------------------------------- /clients/f#/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if test "$OS" = "Windows_NT" 3 | then 4 | # use .Net 5 | 6 | .paket/paket.bootstrapper.exe 7 | exit_code=$? 8 | if [ $exit_code -ne 0 ]; then 9 | exit $exit_code 10 | fi 11 | 12 | .paket/paket.exe restore 13 | exit_code=$? 14 | if [ $exit_code -ne 0 ]; then 15 | exit $exit_code 16 | fi 17 | 18 | packages/FAKE/tools/FAKE.exe $@ --fsiargs build.fsx 19 | else 20 | # use mono 21 | mono .paket/paket.bootstrapper.exe 22 | exit_code=$? 23 | if [ $exit_code -ne 0 ]; then 24 | exit $exit_code 25 | fi 26 | 27 | mono .paket/paket.exe restore 28 | exit_code=$? 29 | if [ $exit_code -ne 0 ]; then 30 | exit $exit_code 31 | fi 32 | mono packages/FAKE/tools/FAKE.exe $@ --fsiargs -d:MONO build.fsx 33 | fi 34 | -------------------------------------------------------------------------------- /clients/clojure/README.md: -------------------------------------------------------------------------------- 1 | # Extreme Carpaccio Clojure starting code 2 | 3 | ## Prerequisites 4 | 5 | You will need **Leiningen 2.0.0** or above installed. 6 | 7 | https://leiningen.org/#install 8 | 9 | ## Development 10 | 1. Fire up a REPL 11 | 2. Hack away, redefine functions they will be hot reloaded, live coding FTW! 12 | 3. Beat the shit out of those crappy java servers :) 13 | 14 | ## Run test 15 | To start a web server and run tests for the application, run: 16 | 17 | ``` 18 | lein midje 19 | ``` 20 | 21 | Tests can be run in watch mode like this 22 | 23 | ``` 24 | lein midje :autotest 25 | ``` 26 | 27 | 28 | ## Running in "production" 29 | To start a web server for the application, listening on , type: 30 | 31 | 32 | ``` 33 | lein ring server [port] 34 | ``` 35 | 36 | -------------------------------------------------------------------------------- /clients/c#/coreWebApi/src/xcarpaccio/Controllers/FeedbackController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.Extensions.Logging; 3 | using XCarpaccio.Models; 4 | 5 | namespace XCarpaccio.Controllers 6 | { 7 | [Route("[controller]")] 8 | public class FeedbackController : Controller 9 | { 10 | ILogger logger; 11 | 12 | public FeedbackController(ILogger logger){ 13 | this.logger = logger; 14 | } 15 | 16 | [HttpPost] 17 | public IActionResult Post([FromBody]Feedback feedBack) 18 | { 19 | logger.LogDebug($"Feedback: Type is {feedBack.Type}, Content is {feedBack.Content}"); 20 | return this.Ok(); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /clients/php/native/tests/functionals/casperjs/04-feedback.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | casper.test.begin('/feedback : Method not allowed', function suite(test) { 4 | casper.start('http://project.loc/feedback', function(response) { 5 | casper.test.assertHttpStatus(405); 6 | casper.test.assertMatch( 7 | response.headers.get('Content-Type'), 8 | new RegExp('|^application/json|', 'i'), 9 | 'Content-Type match the expected value' 10 | ); 11 | }); 12 | casper.then(function() { 13 | var content = JSON.parse(this.getPageContent()); 14 | casper.test.assertEquals(content.error, 'Method not allowed; You must use POST', "Method not allowed"); 15 | }); 16 | casper.run(function () { 17 | test.done(); 18 | }); 19 | }); 20 | 21 | -------------------------------------------------------------------------------- /clients/c#/coreWebApi/src/xcarpaccio/Program.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Linq; 3 | using Microsoft.AspNetCore.Hosting; 4 | using XCarpaccio; 5 | 6 | namespace WebApplication 7 | { 8 | public class Program 9 | { 10 | public static void Main(string[] args) 11 | { 12 | var port = 5000.ToString(); 13 | if (args != null && args.Any()) 14 | { 15 | port = args[0]; 16 | } 17 | 18 | var host = new WebHostBuilder() 19 | .UseKestrel() 20 | .UseContentRoot(Directory.GetCurrentDirectory()) 21 | .UseStartup() 22 | .UseUrls($"http://*:{port}") 23 | .Build(); 24 | 25 | host.Run(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /clients/javascript/express/test/000-server-start.js: -------------------------------------------------------------------------------- 1 | var supertest = require('supertest'); 2 | var Server = require('../server'); 3 | 4 | describe('the server', function () { 5 | var previousPort, server; 6 | beforeEach(function () { 7 | previousPort = process.env.PORT; 8 | process.env.PORT = 21345; 9 | }) 10 | afterEach(function () { 11 | process.env.PORT = previousPort; 12 | }); 13 | 14 | beforeEach(function (done) { 15 | server = new Server(); 16 | server.start(done); 17 | }) 18 | 19 | afterEach(function (done) { 20 | server.stop(done); 21 | }) 22 | 23 | it('starts on the port in PORT', function (done) { 24 | supertest('http://localhost:21345') 25 | .get('/status') 26 | .expect(200) 27 | .expect({up: true}) 28 | .end(done) 29 | }); 30 | }) 31 | -------------------------------------------------------------------------------- /clients/c#/coreWebApi/test/xcarpaccio.tests/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | "buildOptions": { 4 | "debugType": "portable" 5 | }, 6 | "dependencies": { 7 | "xunit": "2.1.0", 8 | "dotnet-test-xunit": "2.2.0-preview2-build1029", 9 | "Microsoft.DotNet.InternalAbstractions": "1.0.0", 10 | "NSubstitute":"2.0.0-rc", 11 | "xcarpaccio": { "target": "project" } 12 | }, 13 | "testRunner": "xunit", 14 | "frameworks": { 15 | "netcoreapp1.1": { 16 | "dependencies": { 17 | "Microsoft.NETCore.App": { 18 | "type": "platform", 19 | "version": "1.1.0" 20 | } 21 | }, 22 | "imports": [ 23 | "dotnet5.0" 24 | ] 25 | } 26 | }, 27 | "tools": { 28 | "Microsoft.DotNet.Watcher.Tools": "1.0.0-preview2-final" 29 | }, 30 | } -------------------------------------------------------------------------------- /clients/clojure/src/extremecarpaccio/core.clj: -------------------------------------------------------------------------------- 1 | (ns extremecarpaccio.core 2 | (:require [compojure.core :refer [routes GET POST]] 3 | [compojure.route :refer [not-found]] 4 | 5 | [ring.middleware.format :refer [wrap-restful-format]] 6 | [ring.util.response :refer [response]])) 7 | 8 | (defn handle-feedback [req] 9 | (let [body (:body-params req)] 10 | (println (:type body) ":" (:content body)) 11 | (response nil))) 12 | 13 | (defn cannot-handle [req] 14 | (println "Cannot handle " req) 15 | (response nil)) 16 | 17 | (def my-app 18 | (-> (routes 19 | (POST "/feedback" [] handle-feedback) 20 | (GET "/ping" [] "pong") 21 | (GET "/" [] "I'm alive!") 22 | (not-found cannot-handle)) 23 | (wrap-restful-format :formats [:json-kw]))) 24 | 25 | 26 | -------------------------------------------------------------------------------- /clients/java/java-httpserver/README.md: -------------------------------------------------------------------------------- 1 | A Java client to with a simple com.sun.net.httpserver.HttpServer implementation. 2 | 3 | ## Dependencies 4 | - maven 3 5 | - JDK 8 6 | 7 | ## Install 8 | - `mvn clean install` 9 | 10 | ## Code 11 | The game server will post orders on `/order` endpoint. 12 | `OrderHttpHandler` inner class inside `MyHttpServer.java` file will handle this so this is where to start coding. 13 | 14 | ## Run 15 | You don't need any application server. No Tomcat, no WAR to deploy. The server is embedded. 16 | 17 | - `PORT=9000 java -jar target/extreme-carpaccio-java-httpserver-1.0-SNAPSHOT-jar-with-dependencies.jar` 18 | 19 | In the example above the server listens on port 9000: [http://localhost:9000/ping](http://localhost:9000/ping) 20 | 21 | You can also launch the server with your IDE. You just have to launch `MyHttpServer` class. It has a `main` method. 22 | -------------------------------------------------------------------------------- /clients/d/README.md: -------------------------------------------------------------------------------- 1 | D language client for extreme-carpaccio game 2 | ============================================ 3 | 4 | This implementation is based on [vibe-d 0.8.6](http://vibed.org/docs). It provides basic routing and models for the following routes: 5 | - POST `/order` (returns 404 by default) 6 | - POST `/feedback` (returns 404 by default) 7 | 8 | The default port is `9000`. You can pass a specific ip and port to the `HTTPServerSettings` object in `app.d` with the following syntax : 9 | 10 | ```d 11 | auto settings = HTTPServerSettings("0.0.0.0:1337"); 12 | ``` 13 | 14 | 15 | How to use this client 16 | ================ 17 | 18 | Install the [dub package manager](http://code.dlang.org/download) and a [D compiler](https://dlang.org/download.html) (dmd is the best option in this context). 19 | 20 | Clone this repository and type `dub` in current directory. 21 | 22 | Have fun! -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "extreme-carpaccio-server", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node bin/www", 7 | "test": "jasmine-node .", 8 | "lint": "eslint javascripts/", 9 | "postinstall": "bower install" 10 | }, 11 | "dependencies": { 12 | "body-parser": "^2.2.0", 13 | "chalk": "^4.1.2", 14 | "debug": "^4.3.4", 15 | "express": "^5.1.0", 16 | "lodash": "^4.17.21", 17 | "url-assembler": "^2.1.1" 18 | }, 19 | "devDependencies": { 20 | "bower": "^1.8.14", 21 | "eslint": "^8.57.0", 22 | "eslint-config-standard": "^17.1.0", 23 | "eslint-plugin-import": "^2.29.1", 24 | "eslint-plugin-node": "^11.1.0", 25 | "eslint-plugin-promise": "^6.1.1", 26 | "eslint-plugin-react": "^7.34.1", 27 | "jasmine-node": "^3.0.0", 28 | "supertest": "^7.0.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /clients/php/silex/tests/functionals/features/bootstrap/ExtremeCarpaccio/ApiContext/PingContext.php: -------------------------------------------------------------------------------- 1 | visitPath('/ping'); 26 | } 27 | 28 | /** 29 | * @Then I must validate my registration 30 | */ 31 | public function iMustValidateMyRegistration() 32 | { 33 | $this->assertResponseContains('pong'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /clients/haskell/README.md: -------------------------------------------------------------------------------- 1 | # Extreme Carpaccio Haskell starting code 2 | 3 | ## Prerequisites 4 | 5 | You will need [Haskell](https://www.haskell.org/) installed with `ghc` 6 | and `cabal` available. 7 | 8 | The application is based on the 9 | [Scotty](https://github.com/scotty-web/scotty) web framework (a Ruby 10 | Sinatra clone). 11 | 12 | ## Build 13 | 14 | To build the application: 15 | 16 | $ cabal install 17 | $ cabal sandbox init 18 | $ cabal build 19 | 20 | Launch it: 21 | 22 | $ .cabal-sandbox/bin/carpaccio 23 | 24 | To run unit-tests: 25 | 26 | $ cabal install --only-dependencies --enable-tests 27 | $ cabal test 28 | 29 | ## Test Driven Development 30 | 31 | Code your algorithm using TDD: 32 | 33 | 1. Launch the `tdd.sh` script 34 | 2. From now, as soon you modify a source file, it will build and test 35 | it. 36 | 3. `ctrl-c` to exit 37 | 38 | Happy coding! 39 | -------------------------------------------------------------------------------- /clients/php/socket/src/Response.php: -------------------------------------------------------------------------------- 1 | formatAnswer($result); 10 | socket_write($spawn, $answer, strlen($answer)); 11 | } 12 | 13 | private function formatAnswer($result) 14 | { 15 | $answer = ""; 16 | if($result != null) { 17 | $answer = json_encode($result); 18 | } 19 | $result = $this->GetHeader($answer); 20 | $result .= $answer; 21 | 22 | return $result; 23 | } 24 | 25 | private function GetHeader(string $answer): string 26 | { 27 | $result = "HTTP/1.0 200 OK\n"; 28 | $result .= "Content-Type: application/json\n"; 29 | $result .= "Content-Length: " . strlen($answer) . "\n"; 30 | $result .= "\r\n"; 31 | return $result; 32 | } 33 | } -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/config/initializers/new_framework_defaults.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | # 3 | # This file contains migration options to ease your Rails 5.0 upgrade. 4 | # 5 | # Read the Guide for Upgrading Ruby on Rails for more info on each option. 6 | 7 | # Make Ruby 2.4 preserve the timezone of the receiver when calling `to_time`. 8 | # Previous versions had false. 9 | ActiveSupport.to_time_preserves_timezone = true 10 | 11 | # Require `belongs_to` associations by default. Previous versions had false. 12 | Rails.application.config.active_record.belongs_to_required_by_default = true 13 | 14 | # Do not halt callback chains when a callback returns false. Previous versions had true. 15 | ActiveSupport.halt_callback_chains_on_return_false = false 16 | 17 | # Configure SSL options to enable HSTS with subdomains. Previous versions had false. 18 | Rails.application.config.ssl_options = { hsts: { subdomains: true } } 19 | -------------------------------------------------------------------------------- /clients/f#/build.fsx: -------------------------------------------------------------------------------- 1 | // include Fake libs 2 | #r "./packages/FAKE/tools/FakeLib.dll" 3 | 4 | open Fake 5 | 6 | // Directories 7 | let buildDir = "./build/" 8 | let deployDir = "./deploy/" 9 | 10 | 11 | // Filesets 12 | let appReferences = 13 | !! "/**/*.csproj" 14 | ++ "/**/*.fsproj" 15 | 16 | // version info 17 | let version = "0.1" // or retrieve from CI server 18 | 19 | // Targets 20 | Target "Clean" (fun _ -> 21 | CleanDirs [buildDir; deployDir] 22 | ) 23 | 24 | Target "Build" (fun _ -> 25 | // compile all projects below src/app/ 26 | MSBuildDebug buildDir "Build" appReferences 27 | |> Log "AppBuild-Output: " 28 | ) 29 | 30 | Target "Deploy" (fun _ -> 31 | !! (buildDir + "/**/*.*") 32 | -- "*.zip" 33 | |> Zip buildDir (deployDir + "ApplicationName." + version + ".zip") 34 | ) 35 | 36 | // Build order 37 | "Clean" 38 | ==> "Build" 39 | ==> "Deploy" 40 | 41 | // start build 42 | RunTargetOrDefault "Build" 43 | -------------------------------------------------------------------------------- /clients/php/native/docker/nginx/site.conf: -------------------------------------------------------------------------------- 1 | server { 2 | server_name project.loc; 3 | root /home/project/web; 4 | 5 | location / { 6 | # try to serve file directly, fallback to front controller 7 | try_files $uri /app.php$is_args$args; 8 | } 9 | 10 | # If you have 2 front controllers for dev|prod use the following line instead 11 | # location ~ ^/(index|index_dev)\.php(/|$) { 12 | location ~ ^/app\.php(/|$) { 13 | fastcgi_pass php:9000; 14 | fastcgi_index app.php; 15 | fastcgi_split_path_info ^(.+\.php)(/.*)$; 16 | include fastcgi_params; 17 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 18 | fastcgi_param HTTPS off; 19 | } 20 | 21 | #return 404 for all php files as we do have a front controller 22 | location ~ \.php$ { 23 | return 404; 24 | } 25 | 26 | error_log /var/log/nginx/project_error.log; 27 | access_log /var/log/nginx/project_access.log; 28 | } 29 | -------------------------------------------------------------------------------- /clients/php/silex/Makefile: -------------------------------------------------------------------------------- 1 | DOCKER_COMPOSE ?= $(shell which docker-compose) 2 | PHP ?= $(shell $(DOCKER_COMPOSE) run php which php) 3 | COMPOSER ?= $(shell $(DOCKER_COMPOSE) run php which composer) 4 | THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST))) 5 | 6 | .PHONY: start 7 | start: 8 | $(DOCKER_COMPOSE) up -d 9 | 10 | .PHONY: stop 11 | stop: 12 | $(DOCKER_COMPOSE) down 13 | 14 | .PHONY: restart 15 | restart: 16 | $(MAKE) -f $(THIS_MAKEFILE) stop 17 | $(MAKE) -f $(THIS_MAKEFILE) start 18 | 19 | .PHONY: up 20 | up: vendor 21 | 22 | composer.lock: composer.json 23 | $(DOCKER_COMPOSE) run php $(PHP) $(COMPOSER) update 24 | 25 | vendor: composer.lock 26 | $(DOCKER_COMPOSE) run php $(PHP) $(COMPOSER) install 27 | 28 | .PHONY: functional-tests 29 | functional-tests: 30 | $(DOCKER_COMPOSE) run php $(PHP) vendor/bin/behat 31 | 32 | .PHONY: unit-tests 33 | unit-tests: 34 | $(DOCKER_COMPOSE) run php $(PHP) vendor/bin/atoum 35 | 36 | .PHONY: tests 37 | tests: functional-tests unit-tests 38 | -------------------------------------------------------------------------------- /clients/php/silex/docker/nginx/site.conf: -------------------------------------------------------------------------------- 1 | server { 2 | server_name project.loc; 3 | root /home/project/web; 4 | 5 | location / { 6 | # try to serve file directly, fallback to front controller 7 | try_files $uri /app.php$is_args$args; 8 | } 9 | 10 | # If you have 2 front controllers for dev|prod use the following line instead 11 | # location ~ ^/(index|index_dev)\.php(/|$) { 12 | location ~ ^/app\.php(/|$) { 13 | fastcgi_pass php:9000; 14 | fastcgi_index app.php; 15 | fastcgi_split_path_info ^(.+\.php)(/.*)$; 16 | include fastcgi_params; 17 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 18 | fastcgi_param HTTPS off; 19 | } 20 | 21 | #return 404 for all php files as we do have a front controller 22 | location ~ \.php$ { 23 | return 404; 24 | } 25 | 26 | error_log /var/log/nginx/project_error.log; 27 | access_log /var/log/nginx/project_access.log; 28 | } 29 | -------------------------------------------------------------------------------- /clients/groovy/groovy-ratpack/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | jcenter() 4 | } 5 | dependencies { 6 | classpath "io.ratpack:ratpack-gradle:0.9.14" 7 | } 8 | } 9 | 10 | apply plugin: "io.ratpack.ratpack-groovy" 11 | apply plugin: "eclipse" 12 | 13 | repositories { 14 | jcenter() 15 | maven { url "http://clinker.netty.io/nexus/content/repositories/snapshots" } 16 | maven { url "http://oss.jfrog.org/artifactory/repo" } 17 | } 18 | 19 | dependencies { 20 | runtime "org.slf4j:slf4j-simple:1.7.5" 21 | 22 | // Spock for testing 23 | testCompile "org.spockframework:spock-core:1.0-groovy-2.4" 24 | 25 | // optional dependencies for using Spock 26 | testCompile "org.hamcrest:hamcrest-core:1.3" // only necessary if Hamcrest matchers are used 27 | testRuntime "cglib:cglib-nodep:3.1" // allows mocking of classes (in addition to interfaces) 28 | testRuntime "org.objenesis:objenesis:2.1" // allows mocking of classes without default constructor (together with CGLIB) 29 | 30 | } 31 | -------------------------------------------------------------------------------- /clients/haskell/carpaccio.cabal: -------------------------------------------------------------------------------- 1 | name: carpaccio 2 | version: 0.0.1 3 | synopsis: A haskell client for extreme-carpaccio 4 | homepage: https://github.com/dlresende/extreme-carpaccio 5 | build-type: Simple 6 | cabal-version: >=1.8 7 | 8 | executable carpaccio 9 | main-is: Main.hs 10 | hs-source-dirs: src 11 | build-depends: base ==4.7.* 12 | , wai 13 | , warp 14 | , http-types 15 | , resourcet 16 | , scotty 17 | , aeson 18 | , text 19 | , bytestring 20 | , blaze-html 21 | , transformers 22 | , mtl 23 | 24 | test-suite spec 25 | main-is: Spec.hs 26 | hs-source-dirs: test src 27 | type: exitcode-stdio-1.0 28 | build-depends: base == 4.* 29 | , hspec >= 1.3 30 | -------------------------------------------------------------------------------- /clients/c#/nancy/extreme-carpaccio.client.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "extreme-carpaccio.client", "extreme-carpaccio.client\extreme-carpaccio.client.csproj", "{35460AA4-B94A-4B64-9418-7243EC3D2F01}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {35460AA4-B94A-4B64-9418-7243EC3D2F01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {35460AA4-B94A-4B64-9418-7243EC3D2F01}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {35460AA4-B94A-4B64-9418-7243EC3D2F01}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {35460AA4-B94A-4B64-9418-7243EC3D2F01}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /clients/c#/dnx-csharp/src/xcarpaccio/modules.cs: -------------------------------------------------------------------------------- 1 | namespace XCarpaccio 2 | { 3 | using Nancy; 4 | using Nancy.ModelBinding; 5 | using System; 6 | using static System.Console; 7 | 8 | public class HomeModule : NancyModule 9 | { 10 | public HomeModule() 11 | { 12 | 13 | Get("/", p => "

DNX-CSharp Carpaccio Online!

"); 14 | 15 | Post("/order", p => 16 | { 17 | WriteLine($"[{DateTime.Now}]"); 18 | return new { Ignored = true }; 19 | }); 20 | 21 | Post("/feedback", p => 22 | { 23 | try 24 | { 25 | var feedback = this.Bind(); 26 | WriteLine($"[{feedback.Type}] {feedback.Content}"); 27 | } 28 | catch (Exception e) 29 | { 30 | int i = 1; 31 | } 32 | return Negotiate.WithStatusCode(200); 33 | 34 | 35 | }); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/config/secrets.yml: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Your secret key is used for verifying the integrity of signed cookies. 4 | # If you change this key, all old signed cookies will become invalid! 5 | 6 | # Make sure the secret is at least 30 characters and all random, 7 | # no regular words or you'll be exposed to dictionary attacks. 8 | # You can use `rails secret` to generate a secure secret key. 9 | 10 | # Make sure the secrets in this file are kept private 11 | # if you're sharing your code publicly. 12 | 13 | development: 14 | secret_key_base: ba8519cb5a196ccb5c48f3228c150253ec5ba55406abefa6dd44c341dd94eee2f6ab2aa484ffda5687e054782b27641083df4e219484b16863dde14bd5dbb4fe 15 | 16 | test: 17 | secret_key_base: 16a85ae14ca8aecbaab5c1b7aa633aca3272f62c67025490dbdcd8a57c5b9f353b0248c1f61b12d3a193b7fba670ee5a5d075a90acbf5235ca58f3ebaf521782 18 | 19 | # Do not keep production secrets in the repository, 20 | # instead read values from the environment. 21 | production: 22 | secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> 23 | -------------------------------------------------------------------------------- /clients/d/source/app.d: -------------------------------------------------------------------------------- 1 | import vibe.d; 2 | 3 | import models.order; 4 | import models.feedback; 5 | 6 | import utils; 7 | 8 | void main() 9 | { 10 | auto router = new URLRouter(); 11 | router.post("/order", &handleOrder); 12 | router.post("/feedback", &handleFeedback); 13 | 14 | auto settings = new HTTPServerSettings(":9000"); 15 | 16 | // Starting the server 17 | listenHTTP(settings, router); 18 | runApplication(); 19 | } 20 | 21 | /** 22 | * Handling POST /order request. 23 | */ 24 | void handleOrder(HTTPServerRequest request, HTTPServerResponse response) 25 | { 26 | info("\n"); 27 | info("Received order JSON: %s", request.json); 28 | 29 | auto order = deserializeJson!Order(request.json); 30 | 31 | throwHTTPError(HTTPStatus.notFound); 32 | } 33 | 34 | /** 35 | * Handling POST /feedback request. 36 | */ 37 | void handleFeedback(HTTPServerRequest request, HTTPServerResponse response) 38 | { 39 | auto feedback = deserializeJson!Feedback(request.json); 40 | 41 | error("Received feedback %s: %s", feedback.type, feedback.content); 42 | } -------------------------------------------------------------------------------- /clients/c#/coreWebApi/src/xcarpaccio/RequestLoggerMiddleware.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Threading.Tasks; 3 | using Microsoft.AspNetCore.Http; 4 | using Microsoft.Extensions.Logging; 5 | 6 | namespace XCarpaccio 7 | { 8 | public class RequestLoggerMiddleware 9 | { 10 | private readonly RequestDelegate _next; 11 | private readonly ILogger _logger; 12 | 13 | public RequestLoggerMiddleware(RequestDelegate next, ILoggerFactory loggerFactory) 14 | { 15 | _next = next; 16 | _logger = loggerFactory.CreateLogger(); 17 | } 18 | 19 | public async Task Invoke(HttpContext context) 20 | { 21 | using (var bodyReader = new StreamReader(context.Request.Body)) 22 | { 23 | string body = await bodyReader.ReadToEndAsync(); 24 | context.Request.Body = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(body)); 25 | _logger.LogDebug(body); 26 | } 27 | await _next.Invoke(context); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /clients/php/native/Makefile: -------------------------------------------------------------------------------- 1 | DOCKER_COMPOSE ?= $(shell which docker-compose) 2 | PHP ?= $(shell $(DOCKER_COMPOSE) run php which php) 3 | COMPOSER ?= $(shell $(DOCKER_COMPOSE) run php which composer) 4 | CASPERJS ?= $(shell $(DOCKER_COMPOSE) run testing which casperjs) 5 | THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST))) 6 | 7 | .PHONY: start 8 | start: 9 | $(DOCKER_COMPOSE) up -d 10 | 11 | .PHONY: stop 12 | stop: 13 | $(DOCKER_COMPOSE) down 14 | 15 | .PHONY: restart 16 | restart: 17 | $(MAKE) -f $(THIS_MAKEFILE) stop 18 | $(MAKE) -f $(THIS_MAKEFILE) start 19 | 20 | .PHONY: up 21 | up: vendor 22 | 23 | composer.lock: composer.json 24 | $(DOCKER_COMPOSE) run php $(PHP) $(COMPOSER) update 25 | 26 | vendor: composer.lock 27 | $(DOCKER_COMPOSE) run php $(PHP) $(COMPOSER) install 28 | 29 | .PHONY: functional-tests 30 | functional-tests: 31 | $(DOCKER_COMPOSE) run testing $(CASPERJS) test /home/project/tests/functionals/casperjs/ 32 | 33 | .PHONY: unit-tests 34 | unit-tests: 35 | $(DOCKER_COMPOSE) run php $(PHP) vendor/bin/atoum 36 | 37 | .PHONY: tests 38 | tests: functional-tests unit-tests 39 | -------------------------------------------------------------------------------- /server/app.js: -------------------------------------------------------------------------------- 1 | var CONFIGURATION_FILE = './configuration.json'; 2 | 3 | var express = require('express'); 4 | var path = require('path'); 5 | var bodyParser = require('body-parser'); 6 | 7 | var services = require('./javascripts/services'); 8 | var repositories = require('./javascripts/repositories'); 9 | var routes = require('./javascripts/routes'); 10 | var config = require('./javascripts/config'); 11 | 12 | 13 | var configuration = new config.Configuration(CONFIGURATION_FILE); 14 | var sellers = new repositories.Sellers(); 15 | var sellerService = new services.SellerService(sellers, configuration); 16 | var orderService = new services.OrderService(configuration); 17 | var dispatcher = new services.Dispatcher(sellerService, orderService, configuration); 18 | 19 | var app = express(); 20 | 21 | app.use(bodyParser.json()); 22 | app.use(bodyParser.urlencoded({ extended: false })); 23 | app.use('/', routes(sellerService, dispatcher)); 24 | app.use(express.static(path.join(__dirname, 'public'))); 25 | 26 | configuration.watch(function() {}, false, 500); 27 | dispatcher.startBuying(1); 28 | 29 | module.exports = app; 30 | -------------------------------------------------------------------------------- /clients/kotlin/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | plugins { 3 | id "org.jetbrains.kotlin.jvm" version "1.3.61" 4 | id 'org.jetbrains.kotlin.plugin.serialization' version '1.3.60' 5 | 6 | id 'java' 7 | id 'application' 8 | id 'idea' 9 | } 10 | 11 | repositories { 12 | jcenter() 13 | } 14 | 15 | group 'extreme-carpaccio' 16 | version '1.0-SNAPSHOT' 17 | 18 | dependencies { 19 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" 20 | implementation "org.jetbrains.kotlin:kotlin-reflect" 21 | implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.14.0" 22 | 23 | implementation "io.ktor:ktor-server-netty:1.3.0" 24 | implementation "io.ktor:ktor-serialization:1.3.0" 25 | implementation "org.slf4j:slf4j-simple:1.7.30" 26 | 27 | testImplementation "org.jetbrains.kotlin:kotlin-test" 28 | testImplementation "io.ktor:ktor-server-test-host:1.3.0" 29 | testImplementation "org.mockito:mockito-core:3.2.4" 30 | } 31 | 32 | application { 33 | mainClassName = 'xcarpaccio.MyServerKt' 34 | } 35 | 36 | idea.module { 37 | downloadSources = true 38 | downloadJavadoc = true 39 | } 40 | -------------------------------------------------------------------------------- /clients/javascript/express/server.js: -------------------------------------------------------------------------------- 1 | var http = require('http'); 2 | var express = require('express'); 3 | var morgan = require('morgan'); 4 | var bodyParser = require('body-parser'); 5 | var routes = require('./lib/routes'); 6 | 7 | module.exports = Server; 8 | 9 | function Server(doLogRequests) { 10 | var app = express(); 11 | app.set('json spaces', 2); 12 | 13 | if (doLogRequests) { 14 | app.use(morgan('dev')); 15 | } 16 | app.use(bodyParser.json()); 17 | 18 | app.get('/status', function (req, res) { 19 | res.json({ up: true }) 20 | }) 21 | 22 | app.post('/order', function (req, res, next) { 23 | routes.order(req, res, next); 24 | }); 25 | app.post('/feedback', function (req, res, next) { 26 | routes.feedback(req, res, next); 27 | }); 28 | 29 | var server = http.createServer(app); 30 | server.start = server.listen.bind(server, process.env.PORT || 3000); 31 | server.stop = server.close.bind(server); 32 | return server; 33 | } 34 | 35 | 36 | if (!module.parent) { 37 | var server = new Server(true); 38 | server.start(function () { 39 | console.log('server listening on port', server.address().port); 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /clients/rust/src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate nickel; 2 | extern crate rustc_serialize; 3 | 4 | use std::collections::BTreeMap; 5 | 6 | use nickel::{ 7 | Nickel, Request, HttpRouter 8 | }; 9 | 10 | use rustc_serialize::json::{Json, ToJson}; 11 | 12 | #[derive(RustcDecodable, RustcEncodable)] 13 | struct Res { 14 | res: String, 15 | } 16 | 17 | impl ToJson for Res { 18 | fn to_json(&self) -> Json { 19 | let mut map = BTreeMap::new(); 20 | map.insert("pong".to_string(), self.res.to_json()); 21 | Json::Object(map) 22 | } 23 | } 24 | 25 | 26 | fn main() { 27 | let mut server = Nickel::new(); 28 | 29 | server.utilize(middleware! { |request| 30 | println!("logging request: {:?}", request.origin.uri); 31 | }); 32 | 33 | 34 | let mut router = Nickel::router(); 35 | 36 | router.get("/hello", middleware!("hello")); 37 | router.get("/ping", middleware! { 38 | let res = Res { 39 | res: "pong".to_string() 40 | }; 41 | res.to_json() 42 | }); 43 | 44 | router.get("**", middleware!("Hello All")); 45 | 46 | server.utilize(router); 47 | server.listen("127.0.0.1:6767"); 48 | } 49 | -------------------------------------------------------------------------------- /clients/c#/coreWebApi/src/xcarpaccio/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "Microsoft.AspNetCore.Server.Kestrel": "1.1.0", 4 | "Microsoft.AspNetCore.Owin": "1.1.0", 5 | "Microsoft.AspNetCore.Mvc": "1.1.0", 6 | "Microsoft.AspNetCore.Routing": "1.1.0", 7 | "Microsoft.Extensions.Configuration.Json": "1.1.0", 8 | "Microsoft.Extensions.Logging": "1.1.0", 9 | "Microsoft.Extensions.Logging.Console": "1.1.0", 10 | "Microsoft.Extensions.Logging.Debug": "1.1.0", 11 | "Microsoft.AspNetCore.Diagnostics":"1.1.0" 12 | }, 13 | 14 | 15 | 16 | "frameworks": { 17 | "netcoreapp1.1": { 18 | "dependencies": { 19 | "Microsoft.NETCore.App": { 20 | "type": "platform", 21 | "version": "1.1.0" 22 | } 23 | }, 24 | "imports": "dnxcore50" 25 | } 26 | }, 27 | 28 | "buildOptions": { 29 | "debugType": "portable", 30 | "emitEntryPoint": true, 31 | "preserveCompilationContext": true 32 | }, 33 | 34 | "tooling": { 35 | "defaultNamespace": "XCarpaccio" 36 | }, 37 | 38 | "commands": { 39 | "web": "Microsoft.AspNet.Server.Kestrel --server.urls=http://*:60000" 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /clients/javascript/node-plain/specs/server_spec.js: -------------------------------------------------------------------------------- 1 | var conf = require('../conf'), 2 | request = require('request'), 3 | server = require('../lib/server'), 4 | serverInstance; 5 | 6 | describe('Default server', function () { 7 | beforeEach(function() { 8 | serverInstance = server.start(conf, function() { 9 | return {total:500}; 10 | }); 11 | }); 12 | afterEach(function() { 13 | serverInstance.close(); 14 | }); 15 | 16 | it('should handle feedback', function(done) { 17 | var feedback = request('http://' + conf.host + ':' + conf.port + '/feedback', function (error, response) { 18 | expect(response.statusCode).toBe(204); 19 | done(); 20 | }); 21 | feedback.write('{type: "INFO", content: "this is my precious feedback"}'); 22 | }); 23 | 24 | it('should handle order', function(done) { 25 | var order = request('http://' + conf.host + ':' + conf.port + '/order', function (error, response, body) { 26 | expect(response.statusCode).toBe(200); 27 | expect(body).toBe('{total:0}'); 28 | done(); 29 | }); 30 | order.write('{prices: [], quantities: [], country: "DE", reduction: "STANDARD"}'); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /clients/typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "extreme-carpaccio-client-typescript", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "jest --watch", 8 | "start-watch": "nodemon --watch 'src/**/*' --ignore 'src/**/*.spec.ts' -e ts,tsx --exec ts-node ./src/server.ts", 9 | "start": "ts-node ./src/server.ts" 10 | }, 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "koa": "^2.7.0", 15 | "koa-bodyparser": "^4.2.1", 16 | "koa-router": "^7.4.0" 17 | }, 18 | "devDependencies": { 19 | "@types/jest": "^23.3.13", 20 | "@types/koa": "^2.0.48", 21 | "@types/koa-bodyparser": "^4.2.1", 22 | "@types/koa-router": "^7.0.39", 23 | "jest": "^24.1.0", 24 | "nodemon": "^1.18.9", 25 | "ts-jest": "^23.10.5", 26 | "ts-node": "^8.0.2", 27 | "typescript": "^3.3.1" 28 | }, 29 | "jest": { 30 | "transform": { 31 | ".(ts|tsx)": "/node_modules/ts-jest/preprocessor.js" 32 | }, 33 | "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$", 34 | "moduleFileExtensions": [ 35 | "ts", 36 | "tsx", 37 | "js" 38 | ] 39 | } 40 | } -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/config/application.rb: -------------------------------------------------------------------------------- 1 | require_relative 'boot' 2 | 3 | require "rails" 4 | # Pick the frameworks you want: 5 | require "active_model/railtie" 6 | require "active_job/railtie" 7 | require "active_record/railtie" 8 | require "action_controller/railtie" 9 | require "action_mailer/railtie" 10 | require "action_view/railtie" 11 | require "action_cable/engine" 12 | # require "sprockets/railtie" 13 | require "rails/test_unit/railtie" 14 | 15 | # Require the gems listed in Gemfile, including any gems 16 | # you've limited to :test, :development, or :production. 17 | Bundler.require(*Rails.groups) 18 | 19 | module RubyRails 20 | class Application < Rails::Application 21 | # Settings in config/environments/* take precedence over those specified here. 22 | # Application configuration should go into files in config/initializers 23 | # -- all .rb files in that directory are automatically loaded. 24 | 25 | # Only loads a smaller set of middleware suitable for API only apps. 26 | # Middleware like session, flash, cookies can be added back manually. 27 | # Skip views, helpers and assets when generating a new resource. 28 | config.api_only = true 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /clients/python/flask-server/client/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Carpaccio server using Flask. 3 | To start the kata, complete the order() function 4 | """ 5 | 6 | from flask import Flask, request, jsonify 7 | import re 8 | 9 | app = Flask(__name__) 10 | 11 | #Main function of the kata 12 | @app.route("/order", methods=['POST']) 13 | def order(): 14 | order = request.get_json() 15 | 16 | #TODO YOUR CODE HERE 17 | 18 | result = {'total': 1000} 19 | # You should probably comment this line before you register your client 20 | return jsonify(result) 21 | 22 | #Server's feedback to your work. 23 | @app.route("/feedback", methods=['POST']) 24 | def feedback(): 25 | feedback = request.get_json() 26 | 27 | #TODO HERE YOU RECEIVE WHAT THE SERVER THINKS ABOUT YOUR WORK 28 | 29 | return jsonify(request.get_json()) 30 | 31 | # Returns 'hello world' on any get request 32 | @app.route("/", methods=['GET']) 33 | @app.route("/", methods=['GET']) 34 | def index2(path=''): 35 | return "hello world" 36 | 37 | @app.route("/ping", methods=['POST']) 38 | def ping(): 39 | return "pong" 40 | # Subject of the Kata. 41 | 42 | def start_server(): 43 | app.run(host='0.0.0.0', 44 | port=int("5000")) 45 | -------------------------------------------------------------------------------- /clients/java/java-httpserver/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | pom.xml.tag 3 | pom.xml.releaseBackup 4 | pom.xml.versionsBackup 5 | pom.xml.next 6 | release.properties 7 | 8 | *.class 9 | 10 | # Package Files # 11 | *.jar 12 | *.war 13 | *.ear 14 | 15 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 16 | hs_err_pid* 17 | 18 | *.pydevproject 19 | .metadata 20 | .gradle 21 | bin/ 22 | tmp/ 23 | *.tmp 24 | *.bak 25 | *.swp 26 | *~.nib 27 | local.properties 28 | .settings/ 29 | .loadpath 30 | 31 | # Eclipse Core 32 | .project 33 | 34 | # External tool builders 35 | .externalToolBuilders/ 36 | 37 | # Locally stored "Eclipse launch configurations" 38 | *.launch 39 | 40 | # CDT-specific 41 | .cproject 42 | 43 | # JDT-specific (Eclipse Java Development Tools) 44 | .classpath 45 | 46 | # PDT-specific 47 | .buildpath 48 | 49 | # sbteclipse plugin 50 | .target 51 | 52 | # TeXlipse plugin 53 | .texlipse 54 | 55 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm 56 | 57 | *.iml 58 | 59 | ## Directory-based project format: 60 | .idea/ 61 | 62 | ## File-based project format: 63 | *.ipr 64 | *.iws 65 | 66 | ## Plugin-specific files: 67 | 68 | # IntelliJ 69 | out/ 70 | 71 | # mpeltonen/sbt-idea plugin 72 | .idea_modules/ 73 | 74 | -------------------------------------------------------------------------------- /clients/php/native/tests/units/src/ExtremeCarpaccio/Model/Order.php: -------------------------------------------------------------------------------- 1 | given( 13 | $country = uniqid('country'), 14 | $product = new \mock\ExtremeCarpaccio\Model\OrderProductInterface, 15 | $this->calling($product)->getUnitPrice = mt_rand(), 16 | $this->calling($product)->getQuantity = mt_rand(), 17 | $products = [ 18 | $product 19 | ], 20 | $reductionType = uniqid('reductionType') 21 | ) 22 | ->if( 23 | $this->newTestedInstance($country, $products, $reductionType) 24 | ) 25 | ->then 26 | ->object($this->testedInstance)->isInstanceOf(\ExtremeCarpaccio\Model\OrderInterface::class) 27 | ->string($this->testedInstance->getCountry())->isEqualTo($country) 28 | ->array($this->testedInstance->getProducts())->isIdenticalTo($products) 29 | ->string($this->testedInstance->getReductionType())->isEqualTo($reductionType) 30 | ; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /clients/php/silex/tests/units/src/ExtremeCarpaccio/Model/Order.php: -------------------------------------------------------------------------------- 1 | given( 13 | $country = uniqid('country'), 14 | $product = new \mock\ExtremeCarpaccio\Model\OrderProductInterface, 15 | $this->calling($product)->getUnitPrice = mt_rand(), 16 | $this->calling($product)->getQuantity = mt_rand(), 17 | $products = [ 18 | $product 19 | ], 20 | $reductionType = uniqid('reductionType') 21 | ) 22 | ->if( 23 | $this->newTestedInstance($country, $products, $reductionType) 24 | ) 25 | ->then 26 | ->object($this->testedInstance)->isInstanceOf(\ExtremeCarpaccio\Model\OrderInterface::class) 27 | ->string($this->testedInstance->getCountry())->isEqualTo($country) 28 | ->array($this->testedInstance->getProducts())->isIdenticalTo($products) 29 | ->string($this->testedInstance->getReductionType())->isEqualTo($reductionType) 30 | ; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /server/javascripts/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var http = require('http') 4 | 5 | var Utils = function (_http) { 6 | this.http = _http || http 7 | } 8 | 9 | Utils.prototype = { 10 | stringify: function (object) { 11 | return JSON.stringify(object) 12 | }, 13 | 14 | jsonify: function (string) { 15 | try { 16 | return JSON.parse(string) 17 | } catch (exception) { 18 | throw new Error('The object "' + string + '" is not a valid json object') 19 | } 20 | }, 21 | 22 | fixPrecision: function (number, precision) { 23 | return parseFloat(number.toFixed(precision)) 24 | }, 25 | 26 | post: function (hostname, port, path, body, onSuccess, onError) { 27 | var bodyStringified = this.stringify(body) 28 | var options = { 29 | hostname: hostname, 30 | port: port, 31 | path: (path || '').replace('//', '/'), 32 | method: 'POST', 33 | headers: { 34 | 'Content-Type': 'application/json', 35 | Accept: 'application/json', 36 | 'Content-Length': bodyStringified.length 37 | } 38 | } 39 | var request = this.http.request(options, onSuccess) 40 | request.on('error', onError || function () {}) 41 | request.write(bodyStringified) 42 | request.end() 43 | } 44 | } 45 | 46 | module.exports = new Utils() 47 | -------------------------------------------------------------------------------- /clients/kotlin/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | pom.xml.tag 3 | pom.xml.releaseBackup 4 | pom.xml.versionsBackup 5 | pom.xml.next 6 | release.properties 7 | 8 | *.class 9 | 10 | # Package Files # 11 | *.jar 12 | !gradle/wrapper/gradle-wrapper.jar 13 | *.war 14 | *.ear 15 | 16 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 17 | hs_err_pid* 18 | 19 | *.pydevproject 20 | .metadata 21 | .gradle 22 | bin/ 23 | tmp/ 24 | *.tmp 25 | *.bak 26 | *.swp 27 | *~.nib 28 | local.properties 29 | .settings/ 30 | .loadpath 31 | 32 | # Eclipse Core 33 | .project 34 | 35 | # External tool builders 36 | .externalToolBuilders/ 37 | 38 | # Locally stored "Eclipse launch configurations" 39 | *.launch 40 | 41 | # CDT-specific 42 | .cproject 43 | 44 | # JDT-specific (Eclipse Java Development Tools) 45 | .classpath 46 | 47 | # PDT-specific 48 | .buildpath 49 | 50 | # sbteclipse plugin 51 | .target 52 | 53 | # TeXlipse plugin 54 | .texlipse 55 | 56 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm 57 | 58 | *.iml 59 | 60 | ## Directory-based project format: 61 | .idea/ 62 | 63 | ## File-based project format: 64 | *.ipr 65 | *.iws 66 | 67 | ## Plugin-specific files: 68 | 69 | # IntelliJ 70 | out/ 71 | build/ 72 | classes/ 73 | 74 | # mpeltonen/sbt-idea plugin 75 | .idea_modules/ 76 | 77 | -------------------------------------------------------------------------------- /clients/groovy/groovy-ratpack/src/test/groovy/ExtremeCarpaccioSpec.groovy: -------------------------------------------------------------------------------- 1 | import ratpack.groovy.test.GroovyRatpackMainApplicationUnderTest 2 | import ratpack.http.Status; 3 | import ratpack.http.client.RequestSpec; 4 | import ratpack.test.ServerBackedApplicationUnderTest 5 | import ratpack.test.http.TestHttpClient 6 | import spock.lang.Specification 7 | 8 | 9 | class ExtremeCarpaccioSpec extends Specification { 10 | 11 | ServerBackedApplicationUnderTest aut = new GroovyRatpackMainApplicationUnderTest() 12 | @Delegate TestHttpClient client = TestHttpClient.testHttpClient(aut) 13 | 14 | 15 | def "a GET on /hello returns 'Hello world!"() { 16 | when: 17 | get("hello") 18 | 19 | then: 20 | response.statusCode == 200 21 | response.body.text == "Hello world!" 22 | } 23 | 24 | def "a POST request on /ping returns 'pong'"() { 25 | when: 26 | post("ping") 27 | 28 | then: 29 | response.statusCode == 200 30 | response.body.text == "pong" 31 | 32 | } 33 | 34 | def "index accepts JSON body"() { 35 | when: 36 | requestSpec { RequestSpec requestSpec -> 37 | requestSpec.body.type("application/json") 38 | requestSpec.body.text('{ "foo": "bar" }') 39 | } 40 | 41 | post("/") 42 | 43 | then: 44 | response.statusCode == 200 45 | response.body.text == "pong" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /server/javascripts/services/reduction.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash') 2 | 3 | function PayThePriceReduction () { 4 | this.name = 'PAY THE PRICE' 5 | this.apply = function (amount) { 6 | return amount 7 | } 8 | } 9 | 10 | function HalfPriceReduction () { 11 | this.name = 'HALF PRICE' 12 | this.apply = function (amount) { 13 | return amount / 2 14 | } 15 | } 16 | 17 | function ReductionStep (sum, reduction) { 18 | this.sum = sum 19 | this.reduction = reduction 20 | } 21 | 22 | function StandardReduction (sum, reduction) { 23 | this.name = 'STANDARD' 24 | var reductions = [ 25 | new ReductionStep(50000, 0.15), 26 | new ReductionStep(10000, 0.10), 27 | new ReductionStep(7000, 0.07), 28 | new ReductionStep(5000, 0.05), 29 | new ReductionStep(1000, 0.03) 30 | ] 31 | 32 | this.apply = function (amount) { 33 | return amount * (1 - this.reductionFor(amount)) 34 | } 35 | this.reductionFor = function (total) { 36 | var reduction = _.result(_.find(reductions, function (reduc) { return reduc.sum <= total }), 'reduction') 37 | if (reduction === undefined) { 38 | return 0 39 | } 40 | return reduction 41 | } 42 | } 43 | 44 | exports.STANDARD = new StandardReduction() 45 | exports.PAY_THE_PRICE = new PayThePriceReduction() 46 | exports.HALF_PRICE = new HalfPriceReduction() 47 | -------------------------------------------------------------------------------- /clients/f#/extreme-carpaccio.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 2013 3 | VisualStudioVersion = 12.0.40629.0 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".paket", ".paket", "{E3B27B6E-D10F-4B36-A712-914C0FC682E7}" 6 | ProjectSection(SolutionItems) = preProject 7 | paket.dependencies = paket.dependencies 8 | EndProjectSection 9 | EndProject 10 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "carpaccio-client", "carpaccio-client\carpaccio-client.fsproj", "{7FB4BC27-7497-475F-BEDA-4B298BA08ED1}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {7FB4BC27-7497-475F-BEDA-4B298BA08ED1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {7FB4BC27-7497-475F-BEDA-4B298BA08ED1}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {7FB4BC27-7497-475F-BEDA-4B298BA08ED1}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {7FB4BC27-7497-475F-BEDA-4B298BA08ED1}.Release|Any CPU.Build.0 = Release|Any CPU 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /clients/java/java-fluent-http/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | extreme-carpaccio 6 | java-fluent-http 7 | jar 8 | 1.0-SNAPSHOT 9 | java-fluent-http 10 | 11 | 12 | UTF-8 13 | UTF-8 14 | UTF-8 15 | 1.8 16 | 1.8 17 | 18 | 19 | 20 | 21 | net.code-story 22 | http 23 | 2.97 24 | 25 | 26 | junit 27 | junit 28 | 4.12 29 | test 30 | 31 | 32 | com.jayway.restassured 33 | rest-assured 34 | 2.4.0 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /clients/c#/coreWebApi/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": ".NET Core Launch (web)", 6 | "type": "coreclr", 7 | "request": "launch", 8 | "preLaunchTask": "build", 9 | "program": "${workspaceRoot}\\src\\xcarpaccio\\bin\\Debug\\netcoreapp1.1\\xcarpaccio.dll", 10 | "args": [], 11 | "cwd": "${workspaceRoot}", 12 | "stopAtEntry": false, 13 | "internalConsoleOptions": "openOnSessionStart", 14 | "launchBrowser": { 15 | "enabled": true, 16 | "args": "${auto-detect-url}", 17 | "windows": { 18 | "command": "cmd.exe", 19 | "args": "/C start ${auto-detect-url}" 20 | }, 21 | "osx": { 22 | "command": "open" 23 | }, 24 | "linux": { 25 | "command": "xdg-open" 26 | } 27 | }, 28 | "env": { 29 | "ASPNETCORE_ENVIRONMENT": "Development" 30 | }, 31 | "sourceFileMap": { 32 | "/Views": "${workspaceRoot}/Views" 33 | } 34 | }, 35 | { 36 | "name": ".NET Core Attach", 37 | "type": "coreclr", 38 | "request": "attach", 39 | "processId": "${command.pickProcess}" 40 | } 41 | ] 42 | } -------------------------------------------------------------------------------- /clients/c#/dnx-csharp/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": ".NET Core Launch (web)", 6 | "type": "coreclr", 7 | "request": "launch", 8 | "preLaunchTask": "build", 9 | "program": "${workspaceRoot}\\src\\xcarpaccio\\bin\\Debug\\netcoreapp1.0\\xcarpaccio.dll", 10 | "args": [], 11 | "cwd": "${workspaceRoot}", 12 | "stopAtEntry": false, 13 | "internalConsoleOptions": "openOnSessionStart", 14 | "launchBrowser": { 15 | "enabled": true, 16 | "args": "${auto-detect-url}", 17 | "windows": { 18 | "command": "cmd.exe", 19 | "args": "/C start ${auto-detect-url}" 20 | }, 21 | "osx": { 22 | "command": "open" 23 | }, 24 | "linux": { 25 | "command": "xdg-open" 26 | } 27 | }, 28 | "env": { 29 | "ASPNETCORE_ENVIRONMENT": "Development" 30 | }, 31 | "sourceFileMap": { 32 | "/Views": "${workspaceRoot}/Views" 33 | } 34 | }, 35 | { 36 | "name": ".NET Core Attach", 37 | "type": "coreclr", 38 | "request": "attach", 39 | "processId": "${command.pickProcess}" 40 | } 41 | ] 42 | } -------------------------------------------------------------------------------- /clients/scala/src/main/scala/main/Server.scala: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import akka.http.scaladsl.marshalling.ToResponseMarshallable 4 | import akka.http.scaladsl.model.ContentTypes.`application/json` 5 | import akka.http.scaladsl.model.HttpEntity 6 | import akka.http.scaladsl.server.{HttpApp, Route} 7 | import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport._ 8 | import io.circe.generic.auto._ 9 | 10 | case class Order(prices: Seq[Float], quantities: Seq[Int], country: String) 11 | 12 | case class Result(total: Float) 13 | 14 | case class Feedback(`type`: String, content: String) 15 | 16 | object Server extends HttpApp with App { 17 | 18 | type ProcessOrder = Order => Option[Float] 19 | 20 | lazy val process: ProcessOrder = { 21 | // TODO To implement 22 | order => Some(0.0f) 23 | } 24 | 25 | override def routes: Route = 26 | path("order") { 27 | post { 28 | entity(as[Order]) { order => 29 | complete { 30 | println("Request received : " + order) 31 | 32 | val total = process(order) 33 | 34 | Result(total.getOrElse(0f)) 35 | } 36 | } 37 | } 38 | } ~ 39 | path("feedback") { 40 | post { 41 | entity(as[Feedback]) { feedback => 42 | complete { 43 | println("Feedback received : " + feedback) 44 | "" 45 | } 46 | } 47 | } 48 | } 49 | 50 | startServer(host = "0.0.0.0", port = 9000) 51 | 52 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Diego Lemos de Resende 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 13 | -------------------------------------------------------------------------------- /clients/java/java-springboot/src/main/java/xcarpaccio/WebController.java: -------------------------------------------------------------------------------- 1 | package xcarpaccio; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.RequestBody; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RequestMethod; 7 | import org.springframework.web.bind.annotation.RestController; 8 | import org.springframework.web.server.ResponseStatusException; 9 | 10 | @RestController 11 | public class WebController { 12 | 13 | @RequestMapping(value = "/order", method = RequestMethod.POST) 14 | public Amount answerQuote(@RequestBody Order order) { 15 | System.out.println("Order received: " + order.toString()); 16 | if (order.prices.length == 0) 17 | return new Amount(computeAmount(order)); 18 | 19 | // Throw a 404 if you don't want to respond to an order, without penalty 20 | throw new ResponseStatusException(HttpStatus.NOT_FOUND, "cannot answer"); 21 | } 22 | 23 | @RequestMapping(value = "/feedback", method = RequestMethod.POST) 24 | public void logFeedback(@RequestBody FeedbackMessage message) { 25 | System.out.println("feedback received: " + message.toString()); 26 | } 27 | 28 | @RequestMapping(value = "/ping", method = RequestMethod.GET) 29 | public String ping() { 30 | System.out.println("ping received"); 31 | return "pong"; 32 | } 33 | 34 | Double computeAmount(Order order) { 35 | return 0.0; 36 | } 37 | } -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | git_source(:github) do |repo_name| 4 | repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") 5 | "https://github.com/#{repo_name}.git" 6 | end 7 | 8 | 9 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' 10 | gem 'rails', '~> 5.0.2' 11 | # Use sqlite3 as the database for Active Record 12 | gem 'sqlite3' 13 | # Use Puma as the app server 14 | gem 'puma', '~> 3.0' 15 | # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder 16 | # gem 'jbuilder', '~> 2.5' 17 | # Use Redis adapter to run Action Cable in production 18 | # gem 'redis', '~> 3.0' 19 | # Use ActiveModel has_secure_password 20 | # gem 'bcrypt', '~> 3.1.7' 21 | 22 | # Use Capistrano for deployment 23 | # gem 'capistrano-rails', group: :development 24 | 25 | # Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible 26 | # gem 'rack-cors' 27 | 28 | group :development, :test do 29 | # Call 'byebug' anywhere in the code to stop execution and get a debugger console 30 | gem 'byebug', platform: :mri 31 | end 32 | 33 | group :development do 34 | gem 'listen', '~> 3.0.5' 35 | # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring 36 | gem 'spring' 37 | gem 'spring-watcher-listen', '~> 2.0.0' 38 | end 39 | 40 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem 41 | gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] 42 | -------------------------------------------------------------------------------- /clients/c#/nancy/NancyApplication1/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("NancyApplication1")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("NancyApplication1")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("cc3adbca-2baf-46d6-96f3-5438dfe2189e")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /clients/c#/nancy/extreme-carpaccio.client/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("katazon.client")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("katazon.client")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("cc3adbca-2baf-46d6-96f3-5438dfe2189e")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /clients/haskell/src/Main.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE OverloadedStrings #-} 2 | import Data.Aeson 3 | import Data.Text 4 | import Data.Monoid 5 | import Control.Applicative ((<$>), (<*>)) 6 | import Control.Monad 7 | import Control.Monad.Trans (liftIO) 8 | import Web.Scotty 9 | import Model 10 | 11 | instance FromJSON Order where 12 | parseJSON (Object v) = 13 | Order <$> 14 | (v .: "prices") <*> 15 | (v .: "quantities") <*> 16 | (v .: "country") <*> 17 | (v .: "reduction") 18 | 19 | data Feedback = Feedback 20 | { feedbackType :: Text 21 | , content :: Text 22 | } deriving (Show) 23 | 24 | instance FromJSON Feedback where 25 | parseJSON (Object v) = 26 | Feedback <$> 27 | (v .: "type") <*> 28 | (v .: "content") 29 | parseJSON _ = mzero 30 | 31 | instance ToJSON Quantity where 32 | toJSON (Quantity total) = object [ "total" .= total] 33 | 34 | main :: IO () 35 | main = scotty 8000 $ do 36 | 37 | get "/" $ do 38 | html "Hello extreme-carpaccio!" 39 | 40 | post "/feedback" $ do 41 | b <- body 42 | f <- case decode b of 43 | Just x -> return x 44 | Nothing -> fail "no feedback" 45 | 46 | liftIO $ print $ show (f :: Feedback) 47 | html "Thanx for this very usefull feedback" 48 | 49 | post "/order" $ do 50 | b <- body 51 | o <- case decode b of 52 | Just x -> return x 53 | Nothing -> fail "no order" 54 | 55 | liftIO $ print $ show (o :: Order) 56 | 57 | let answer = computeTotal o 58 | 59 | liftIO $ print $ show answer 60 | 61 | raw $ encode $ answer 62 | -------------------------------------------------------------------------------- /server/javascripts/routes.js: -------------------------------------------------------------------------------- 1 | var express = require('express') 2 | var _ = require('lodash') 3 | 4 | module.exports = function (sellerService, dispatcher) { 5 | var router = express.Router() 6 | var OK = 200 7 | var BAD_REQUEST = 400 8 | var UNAUTHORIZED = 401 9 | 10 | router.get('/sellers', function (request, response) { 11 | // seller view is returned, to prevent any confidential information leaks 12 | var sellerViews = _.map(sellerService.allSellers(), function (seller) { 13 | return { 14 | cash: seller.cash, 15 | name: seller.name, 16 | online: seller.online 17 | } 18 | }) 19 | response.status(OK).send(sellerViews) 20 | }) 21 | 22 | router.get('/sellers/history', function (request, response) { 23 | var chunk = request.query.chunk || 10 24 | response.status(OK).send(sellerService.getCashHistory(chunk)) 25 | }) 26 | 27 | router.post('/seller', function (request, response) { 28 | var sellerName = request.body.name 29 | var sellerUrl = request.body.url 30 | var sellerPwd = request.body.password 31 | 32 | if (_.isEmpty(sellerName) || _.isEmpty(sellerUrl) || _.isEmpty(sellerPwd)) { 33 | response.status(BAD_REQUEST).send({ message: 'missing name, password or url' }) 34 | } else if (sellerService.isAuthorized(sellerName, sellerPwd)) { 35 | sellerService.register(sellerUrl, sellerName, sellerPwd) 36 | response.status(OK).end() 37 | } else { 38 | response.status(UNAUTHORIZED).send({ message: 'invalid name or password' }) 39 | } 40 | }) 41 | 42 | return router 43 | } 44 | -------------------------------------------------------------------------------- /clients/java/java-spark/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | extreme-carpaccio 6 | extreme-carpaccio-spark 7 | 1.0-SNAPSHOT 8 | 9 | 10 | 1.8 11 | 1.8 12 | UTF-8 13 | 14 | 15 | 16 | 17 | com.sparkjava 18 | spark-core 19 | 2.2 20 | 21 | 22 | 23 | com.google.code.gson 24 | gson 25 | 2.3.1 26 | 27 | 28 | 29 | org.assertj 30 | assertj-core 31 | 3.0.0 32 | test 33 | 34 | 35 | 36 | junit 37 | junit 38 | 4.12 39 | test 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /clients/go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "io/ioutil" 6 | "log" 7 | "net/http" 8 | "os" 9 | 10 | "fmt" 11 | ) 12 | 13 | type Order struct { 14 | Prices []float32 15 | Quantities []int 16 | Country string 17 | Reduction string 18 | } 19 | 20 | type Reply struct { 21 | Total float32 `json:"total"` 22 | } 23 | 24 | func main() { 25 | http.HandleFunc("/order", handler) 26 | http.HandleFunc("/feedback", func(rw http.ResponseWriter, req *http.Request) { 27 | defer req.Body.Close() 28 | 29 | body, err := ioutil.ReadAll(req.Body) 30 | if err != nil { 31 | fmt.Printf("error reading body: %v\n", err) 32 | rw.WriteHeader(204) 33 | return 34 | } 35 | 36 | fmt.Printf("Feedback: %s\n", body) 37 | 38 | rw.WriteHeader(200) 39 | }) 40 | 41 | err := http.ListenAndServe(fmt.Sprintf(":%s", getPort()), nil) 42 | if err != nil { 43 | log.Fatal("Listen and serve:", err) 44 | } 45 | } 46 | 47 | func handler(rw http.ResponseWriter, req *http.Request) { 48 | defer req.Body.Close() 49 | 50 | body, err := ioutil.ReadAll(req.Body) 51 | if err != nil { 52 | fmt.Printf("error reading body: %v\n", err) 53 | rw.WriteHeader(204) 54 | return 55 | } 56 | 57 | var order Order 58 | json.Unmarshal(body, &order) 59 | 60 | fmt.Printf("Got order: %#v\n", order) 61 | 62 | rw.Header().Add("Content-Type", "application/json") 63 | rw.WriteHeader(200) 64 | // encoder := json.NewEncoder(rw) 65 | // encoder.Encode(Reply{0}) 66 | } 67 | 68 | func getPort() string { 69 | port := os.Getenv("PORT") 70 | if port == "" { 71 | return "9000" 72 | } 73 | return port 74 | } 75 | -------------------------------------------------------------------------------- /clients/f#/carpaccio-client/carpaccio-client.fs: -------------------------------------------------------------------------------- 1 | module CarpaccioClient 2 | open Suave 3 | open Suave.Filters 4 | open Suave.Operators 5 | open Suave.Successful 6 | open System.Net 7 | open System.Text 8 | open Newtonsoft.Json 9 | open CarpaccioModel 10 | 11 | let decodeUTF8ContentToString (request:HttpRequest) = 12 | Encoding.UTF8.GetString request.rawForm 13 | 14 | let deserialize<'a> (s:string) : 'a option = 15 | try 16 | Some (JsonConvert.DeserializeObject<'a> s) 17 | with 18 | _ -> printfn "ERROR can't deserialize : %s" s 19 | None 20 | 21 | let handleFeedback (r:HttpRequest) = 22 | let feedback = decodeUTF8ContentToString >> deserialize <| r 23 | printfn "Feedback -> %A" <| feedback 24 | OK "" 25 | 26 | let handleOrder (r:HttpRequest) = 27 | let order = decodeUTF8ContentToString >> deserialize <| r 28 | printfn "order received -> %A" order 29 | OK "" 30 | 31 | let app = 32 | choose [ 33 | GET >=> choose 34 | [ path "/order" >=> OK "Hello World!" 35 | path "/ping" >=> OK "pong" ] 36 | POST >=> choose 37 | [ path "/order" >=> request ( fun r -> r |> handleOrder ) 38 | path "/feedback" >=> request (fun r -> r |> handleFeedback ) ] 39 | ] 40 | 41 | let port = Sockets.Port.Parse <| "8080" 42 | let ip = IPAddress.Any 43 | 44 | let serverConfig = 45 | { defaultConfig with 46 | bindings = [ HttpBinding.mk HTTP ip port ] 47 | } 48 | 49 | [] 50 | let main argv = 51 | printfn "Starting server ..." 52 | startWebServer serverConfig app 53 | 0 54 | -------------------------------------------------------------------------------- /clients/php/native/tests/functionals/casperjs/03-order.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | casper.test.begin('/order : Managed data', function suite(test) { 4 | var managedOrders = [ 5 | { 6 | order: { 7 | 'prices[]': [15.99], 8 | 'quantities[]': [1], 9 | 'country': 'ES', 10 | 'reduction': 'STANDARD' 11 | }, 12 | expected: { 13 | value: 19.03 14 | } 15 | }, 16 | { 17 | order: { 18 | 'prices[]': [4.1,8.03,86.83,65.62,44.82], 19 | 'quantities[]': [10,3,5,4,5], 20 | 'country': 'AT', 21 | 'reduction':'STANDARD' 22 | }, 23 | expected: { 24 | value: 1166.62 25 | } 26 | } 27 | ]; 28 | 29 | casper.each(managedOrders, function(self, orderData) { 30 | self.thenOpen('http://project.loc/order', { 31 | method: 'post', 32 | data: orderData.order 33 | }).then(function(response) { 34 | casper.test.assertHttpStatus(200); 35 | casper.test.assertMatch( 36 | response.headers.get('Content-Type'), 37 | new RegExp('|^application/json|', 'i'), 38 | 'Content-Type match the expected value' 39 | ); 40 | var content = JSON.parse(this.getPageContent()); 41 | casper.test.assertEquals(content.total, orderData.expected.value, 'Order total computation equals the expected value'); 42 | }); 43 | }).run(function () { 44 | test.done(); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /clients/java/java-fluent-http/src/main/java/xcarpaccio/WebConfiguration.java: -------------------------------------------------------------------------------- 1 | package xcarpaccio; 2 | 3 | import net.codestory.http.Configuration; 4 | import net.codestory.http.payload.Payload; 5 | import net.codestory.http.routes.Routes; 6 | 7 | public class WebConfiguration implements Configuration { 8 | 9 | private final Logger logger = new Logger(); 10 | 11 | @Override 12 | public void configure(Routes routes) { 13 | routes. 14 | get("/ping", "pong"). 15 | post("/feedback", (context) -> { 16 | Message message = context.extract(Message.class); 17 | logger.log(message.type + ": " + message.content); 18 | return new Payload(204); 19 | }). 20 | post("/order", (context -> { 21 | String method = context.method(); 22 | String uri = context.uri(); 23 | String body = context.extract(String.class); 24 | logger.log(method + " " + uri + " " + body); 25 | Order order = context.extract(Order.class); 26 | logger.log("Unserialized order: " + order); 27 | 28 | // Use the following line to choose not to handle an order 29 | return new Payload("application/json", "", 200); 30 | 31 | // Use the following lines to return a total: 32 | // double total = 42.0; 33 | // Answer answer = new Answer(total); 34 | // return new Payload("application/json", answer, 200); 35 | })) 36 | ; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /clients/php/socket/src/Server.php: -------------------------------------------------------------------------------- 1 | _reader = $reader; 17 | $this->_response = $response; 18 | $this->_output = $output; 19 | $this->_feedbackMapper = $feedbackMapper; 20 | } 21 | 22 | public function Start() 23 | { 24 | $this->_reader->Listen(5000); 25 | do { 26 | $readerSpawn = $this->_reader->Read(); 27 | $resource = $this->_reader->GetResource(); 28 | if($resource == "Ping"){ 29 | $this->_output->Print($resource); 30 | $this->_response->Post("pong", $readerSpawn); 31 | } 32 | if ($resource == "Order") { 33 | $this->_output->Print($resource . " : " . $this->_reader->GetMessage()); 34 | 35 | //$result = new Result(30); //TODO compute correct result or you'll get a penalty 36 | $result = null; 37 | 38 | $this->_response->Post($result, $readerSpawn); 39 | } 40 | if ($resource == "Feedback"){ 41 | $feedbackMessage = $this->_feedbackMapper->setValues($this->_reader->GetMessage()); 42 | $this->_output->Print($feedbackMessage->GetType() . " : " . $feedbackMessage->GetMessage()); 43 | } 44 | } 45 | while($readerSpawn); 46 | $this->_reader->Close(); 47 | } 48 | } -------------------------------------------------------------------------------- /clients/c#/coreWebApi/src/xcarpaccio/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Logging; 6 | 7 | namespace XCarpaccio 8 | { 9 | public class Startup 10 | { 11 | public Startup(IHostingEnvironment env) 12 | { 13 | var builder = new ConfigurationBuilder() 14 | .SetBasePath(env.ContentRootPath) 15 | .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) 16 | .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); 17 | 18 | Configuration = builder.Build(); 19 | } 20 | 21 | public IConfigurationRoot Configuration { get; } 22 | 23 | // This method gets called by the runtime. Use this method to add services to the container. 24 | public void ConfigureServices(IServiceCollection services) 25 | { 26 | services.AddMvc(); 27 | } 28 | 29 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 30 | public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 31 | { 32 | loggerFactory.AddConsole(Configuration.GetSection("Logging")); 33 | loggerFactory.AddDebug(); 34 | app.UseMiddleware(); 35 | app.UseMvc(routes => 36 | { 37 | routes.MapRoute( 38 | name: "default", 39 | template: "{controller=Home}/{action=Index}/{id?}"); 40 | }); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /server/javascripts/config.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var utils = require('../javascripts/utils') 3 | var _ = require('lodash') 4 | var chalk = require('chalk') 5 | 6 | var Configuration = function (filepath) { 7 | this.filepath = filepath 8 | this.props = {} 9 | } 10 | 11 | Configuration.prototype = (function () { 12 | function loadFile (self, callback) { 13 | console.info(chalk.red('Reloading ' + self.filepath)) 14 | 15 | fs.readFile(self.filepath, function (err, data) { 16 | if (err) { 17 | console.error('%j', err) 18 | } else { 19 | try { 20 | self.props = utils.jsonify(data) 21 | 22 | if (typeof callback !== 'undefined') { 23 | callback(err) 24 | } 25 | } catch (exception) { 26 | console.error('Oops something wrong happened', exception) 27 | } 28 | } 29 | }) 30 | } 31 | 32 | function readContent (self) { 33 | console.info('Reading %s.', self.filepath) 34 | var fileContent = fs.readFileSync(self.filepath) 35 | return utils.jsonify(fileContent) 36 | } 37 | 38 | return { 39 | load: function (callback) { 40 | return loadFile(this, callback) 41 | }, 42 | 43 | all: function () { 44 | var self = this 45 | 46 | if (_.isEmpty(self.props)) { 47 | self.props = readContent(self) 48 | } 49 | 50 | return self.props 51 | }, 52 | 53 | watch: function (callback, watchOnce, interval) { 54 | var self = this 55 | 56 | fs.watchFile(self.filepath, { persistent: !watchOnce, interval: interval }, function (curr, prev) { 57 | self.load(callback) 58 | }) 59 | } 60 | } 61 | })() 62 | 63 | var exports = module.exports 64 | exports.Configuration = Configuration 65 | -------------------------------------------------------------------------------- /clients/java/java-fluent-http/src/test/java/xcarpaccio/MyFluentHttpServerTest.java: -------------------------------------------------------------------------------- 1 | package xcarpaccio; 2 | 3 | import static com.jayway.restassured.RestAssured.given; 4 | import static com.jayway.restassured.RestAssured.when; 5 | import static com.jayway.restassured.http.ContentType.JSON; 6 | import static org.hamcrest.Matchers.containsString; 7 | import static org.hamcrest.Matchers.equalTo; 8 | 9 | import org.junit.Test; 10 | import com.jayway.restassured.RestAssured; 11 | 12 | public class MyFluentHttpServerTest { 13 | 14 | private static final int PORT = 9001; 15 | private static final MyFluentHttpServer myFluentHttpServer = new MyFluentHttpServer(PORT); 16 | 17 | static { 18 | RestAssured.port = PORT; 19 | } 20 | 21 | @Test public void 22 | should_respond_pong_when_requesting_ping() { 23 | when(). 24 | get("/ping"). 25 | then(). 26 | statusCode(200). 27 | body(containsString("pong")) 28 | ; 29 | } 30 | 31 | @Test public void 32 | should_post_feedback() { 33 | given(). 34 | contentType(JSON). 35 | body(new Message("myType", "myContent")). 36 | when(). 37 | post("/feedback"). 38 | then(). 39 | statusCode(204) 40 | ; 41 | } 42 | 43 | @Test public void 44 | should_post_an_order() { 45 | given(). 46 | contentType(JSON). 47 | body("{\"prices\":[31.01],\"quantities\":[8],\"names\":[\"Tea\"],\"country\":\"IT\",\"reduction\":\"STANDARD\"}"). 48 | when(). 49 | post("/order"). 50 | then(). 51 | statusCode(200). 52 | body(equalTo("")) 53 | ; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /clients/erlang/README.md: -------------------------------------------------------------------------------- 1 | # Get Started 2 | 3 | Compile the application using rebar: 4 | 5 | ./rebar get-deps compile 6 | 7 | Start the application: 8 | 9 | erl -pa ebin deps/*/ebin -s xcarpaccio 10 | 11 | Execute tests: 12 | 13 | ./rebar compile eunit skip_deps=true 14 | 15 | Execute tests for dependencies too: 16 | 17 | ./rebar compile eunit 18 | 19 | 20 | # Developer Notes 21 | 22 | ``` 23 | $ wget https://github.com/rebar/rebar/wiki/rebar 24 | $ chmod +x rebar 25 | ``` 26 | 27 | ## Live code reload 28 | 29 | **First shell: start the application** 30 | 31 | ``` 32 | $ erl -pa ebin deps/*/ebin -s xcarpaccio -sname bob -noshell 33 | ``` 34 | 35 | **Second Shell: remote shell on the first shell** 36 | 37 | ``` 38 | $ erl -sname razowski -remsh bob@Mentem 39 | → c("src/xcarpaccio_webhandler"). 40 | ``` 41 | 42 | or 43 | 44 | ``` 45 | $ erl -sname razowski -remsh bob@Mentem 46 | → cd("src/"). 47 | → c(xcarpaccio_webhandler). 48 | ``` 49 | 50 | 51 | **Warning** 52 | By default, beam files - created from shell compilation - are not created within the `ebin/` folder but in the root folder (or in `src` if you changed the current directory). You should take care to recompile the application if it is restarted from scratch afterwards. Otherwise you may still run old behaviors from previous beam files. 53 | 54 | A solution is to define the output dir of the compilation. 55 | 56 | ``` 57 | $ erl -sname razowski -remsh bob@Mentem 58 | → cd("src/"). 59 | → OPTs = [{outdir,"../ebin"}]. 60 | → c(xcarpaccio_webhandler, OPTs). 61 | ``` 62 | 63 | # Resources 64 | 65 | * [cowboy](https://github.com/extend/cowboy): Small, fast, modular HTTP server written in Erlang 66 | * [jsx](https://github.com/talentdeficit/jsx): JSON parser (in erlang no NIF) 67 | * [rebar](https://github.com/rebar/rebar) 68 | -------------------------------------------------------------------------------- /clients/erlang/src/xcarpaccio_app.erl: -------------------------------------------------------------------------------- 1 | -module(xcarpaccio_app). 2 | 3 | -behaviour(application). 4 | 5 | %% Application callbacks 6 | -export([start/2, stop/1]). 7 | 8 | -define(C_ACCEPTORS, 100). 9 | 10 | %% =================================================================== 11 | %% Application callbacks 12 | %% =================================================================== 13 | 14 | start(_StartType, _StartArgs) -> 15 | Routes = routes(), 16 | Dispatch = cowboy_router:compile(Routes), 17 | Port = port(), 18 | TransOpts = [{port, Port}], 19 | ProtoOpts = [{env, [{dispatch, Dispatch}]}], 20 | HttpStart = cowboy:start_http(http, ?C_ACCEPTORS, TransOpts, ProtoOpts), 21 | io:format("cowboy:start_http (on port ~p): ~p~n", [Port, HttpStart]), 22 | {ok, _} = HttpStart. 23 | 24 | stop(_State) -> 25 | ok. 26 | 27 | %% =================================================================== 28 | %% Internal functions 29 | %% =================================================================== 30 | 31 | %% 32 | %% Cowboy routes mapping - 33 | %% route does not support HTTP Method constraint 34 | %% https://groups.google.com/forum/#!topic/erlang-programming/-v2sBGxhDMY 35 | %% 36 | %% To prevent path duplication, dispatching is done in the handler itself 37 | %% 38 | routes() -> 39 | [ 40 | {'_', [ 41 | {"/[...]", xcarpaccio_webhandler, []} 42 | ]} 43 | ]. 44 | 45 | %% 46 | %% Retrieve the PORT either from an os environment variable 47 | %% e.g. in Heroku environment, or from the application conf. 48 | %% 49 | port() -> 50 | case os:getenv("PORT") of 51 | false -> 52 | {ok, Port} = application:get_env(http_port), 53 | Port; 54 | Other -> 55 | list_to_integer(Other) 56 | end. 57 | -------------------------------------------------------------------------------- /clients/c#/nancy/extreme-carpaccio.client/IndexModule.cs: -------------------------------------------------------------------------------- 1 | 2 | using System.IO; 3 | using System.Net; 4 | using System.Text; 5 | 6 | namespace xCarpaccio.client 7 | { 8 | using Nancy; 9 | using System; 10 | using Nancy.ModelBinding; 11 | 12 | public class IndexModule : NancyModule 13 | { 14 | public IndexModule() 15 | { 16 | Post["/order"] = _ => 17 | { 18 | var order = this.Bind(); 19 | var bill = HandlerOrder(order); 20 | if (bill == null) 21 | { 22 | return new {}; 23 | 24 | } 25 | else 26 | { 27 | return bill; 28 | 29 | } 30 | 31 | }; 32 | 33 | Post["/feedback"] = _ => 34 | { 35 | var feedback = this.Bind(); 36 | 37 | HandleFeedback(feedback); 38 | return Negotiate.WithStatusCode(HttpStatusCode.OK); 39 | }; 40 | } 41 | 42 | private string RequestAsString() 43 | { 44 | string request; 45 | using (var reader = new StreamReader(Request.Body, Encoding.UTF8)) 46 | { 47 | request = reader.ReadToEnd(); 48 | } 49 | return request; 50 | } 51 | 52 | private void HandleFeedback(Feedback feedback) 53 | { 54 | Console.Write("Type: {0}: ", feedback.type); 55 | Console.WriteLine(feedback.content); 56 | } 57 | 58 | 59 | private Bill HandlerOrder(Order order) 60 | { 61 | // TODO HERE. Return null if you do not what to return a total 62 | return null; 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/config/environments/development.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # In the development environment your application's code is reloaded on 5 | # every request. This slows down response time but is perfect for development 6 | # since you don't have to restart the web server when you make code changes. 7 | config.cache_classes = false 8 | 9 | # Do not eager load code on boot. 10 | config.eager_load = false 11 | 12 | # Show full error reports. 13 | config.consider_all_requests_local = true 14 | 15 | # Enable/disable caching. By default caching is disabled. 16 | if Rails.root.join('tmp/caching-dev.txt').exist? 17 | config.action_controller.perform_caching = true 18 | 19 | config.cache_store = :memory_store 20 | config.public_file_server.headers = { 21 | 'Cache-Control' => 'public, max-age=172800' 22 | } 23 | else 24 | config.action_controller.perform_caching = false 25 | 26 | config.cache_store = :null_store 27 | end 28 | 29 | # Don't care if the mailer can't send. 30 | config.action_mailer.raise_delivery_errors = false 31 | 32 | config.action_mailer.perform_caching = false 33 | 34 | # Print deprecation notices to the Rails logger. 35 | config.active_support.deprecation = :log 36 | 37 | # Raise an error on page load if there are pending migrations. 38 | config.active_record.migration_error = :page_load 39 | 40 | 41 | # Raises error for missing translations 42 | # config.action_view.raise_on_missing_translations = true 43 | 44 | # Use an evented file watcher to asynchronously detect changes in source code, 45 | # routes, locales, etc. This feature depends on the listen gem. 46 | config.file_watcher = ActiveSupport::EventedFileUpdateChecker 47 | end 48 | -------------------------------------------------------------------------------- /clients/php/socket/src/Reader.php: -------------------------------------------------------------------------------- 1 | _resource; 22 | } 23 | 24 | public function GetMessage() 25 | { 26 | return $this->_message; 27 | } 28 | 29 | public function Listen($port) 30 | { 31 | $host = "0.0.0.0"; 32 | $this->_socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); 33 | socket_bind($this->_socket, $host, $port); 34 | socket_listen($this->_socket, SOMAXCONN); 35 | } 36 | 37 | public function Read() 38 | { 39 | 40 | $spawn = socket_accept($this->_socket); 41 | $body = socket_read($spawn, 1048576); 42 | $this->_message = $this->GetMessageFrom($body); 43 | $this->_resource = $this->GetResourceFrom($body); 44 | return $spawn; 45 | 46 | } 47 | 48 | public function Close() 49 | { 50 | socket_close($this->_socket); 51 | } 52 | 53 | public function GetMessageFrom(string $body) 54 | { 55 | $parts = explode("\r\n\r\n", $body); 56 | 57 | if ($parts) 58 | { 59 | $message = $parts[1]; 60 | } 61 | 62 | return $message; 63 | } 64 | 65 | public function GetResourceFrom(string $body) 66 | { 67 | $parts = explode("\r\n\r\n", $body); 68 | $type = ""; 69 | if ($parts) 70 | { 71 | $headers = array_shift($parts); 72 | $matches = preg_split('/ /', $headers); 73 | $type = str_replace("/", "", $matches[1]); 74 | } 75 | 76 | return ucfirst($type); 77 | } 78 | } -------------------------------------------------------------------------------- /clients/java/java-httpserver/src/test/java/xcarpaccio/AbstractHttpServerTest.java: -------------------------------------------------------------------------------- 1 | package xcarpaccio; 2 | 3 | import java.io.DataOutputStream; 4 | import java.io.IOException; 5 | import java.net.HttpURLConnection; 6 | import java.net.ProtocolException; 7 | import java.net.URL; 8 | 9 | import static xcarpaccio.StringUtils.stringify; 10 | 11 | public abstract class AbstractHttpServerTest 12 | { 13 | private static final String UTF_8 = "utf-8"; 14 | 15 | protected String get(String url) throws IOException { 16 | return get(url, ""); 17 | } 18 | 19 | protected String get(String url, String query) throws IOException { 20 | URL localhost = new URL(url + "?" + query); 21 | HttpURLConnection connection = (HttpURLConnection) localhost.openConnection(); 22 | connection.setRequestMethod( "GET" ); 23 | connection.disconnect(); 24 | return stringify(connection.getInputStream()); 25 | } 26 | 27 | protected String post(String path, String body) throws IOException { 28 | URL url = new URL(path); 29 | HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 30 | connection.setDoOutput(true); 31 | connection.setDoInput(true); 32 | connection.setInstanceFollowRedirects(false); 33 | connection.setRequestMethod("POST"); 34 | connection.setRequestProperty("Content-Type", "application/json"); 35 | connection.setRequestProperty("charset", UTF_8); 36 | connection.setRequestProperty("Content-Length", Integer.toString(body.length())); 37 | connection.setUseCaches(false); 38 | try( DataOutputStream wr = new DataOutputStream( connection.getOutputStream())) { 39 | wr.write( body.getBytes(UTF_8) ); 40 | return stringify(connection.getInputStream()); 41 | } finally { 42 | connection.disconnect(); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /server/specs/config_spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _1000_MILLIS_TIMEOUT = 1000; 4 | var _200_MILLIS = 200; 5 | 6 | var fs = require('fs'), 7 | Configuration = require('../javascripts/config').Configuration; 8 | 9 | describe('Configuration', function(){ 10 | var config, 11 | synchronized, 12 | configFilepath = "specs/config.json.tmp"; 13 | 14 | beforeEach(function () { 15 | fs.writeFileSync(configFilepath, '{"reduction": "STANDARD"}'); 16 | config = new Configuration(configFilepath); 17 | synchronized = false; 18 | }); 19 | 20 | it('should load configuration from file', function() { 21 | runs(function() { 22 | config.load(function (err) { 23 | expect(err).toBeNull(); // Arnauld a voulu faire ce test, parce qu'il trouve que c'est une bonne idee! 24 | synchronized = true; 25 | }); 26 | }); 27 | 28 | waitsFor(function() { 29 | return synchronized; 30 | }, "Properties should be loaded in time", _1000_MILLIS_TIMEOUT); 31 | 32 | runs(function() { 33 | var properties = config.all(); 34 | expect(properties).toEqual({reduction: 'STANDARD'}); 35 | }); 36 | }); 37 | 38 | it('should reload configuration on the fly', function() { 39 | runs(function() { 40 | config.watch(function() { 41 | synchronized = true; 42 | }, true, _200_MILLIS); 43 | 44 | fs.writeFileSync(configFilepath, '{"reduction": "HALF PIPE"}'); 45 | }); 46 | 47 | waitsFor(function() { 48 | return synchronized; 49 | }, "File change should be detected", _1000_MILLIS_TIMEOUT); 50 | 51 | runs(function() { 52 | var properties = config.all(); 53 | expect(properties).toEqual({reduction: 'HALF PIPE'}); 54 | }); 55 | }); 56 | }); 57 | -------------------------------------------------------------------------------- /clients/ruby/ruby-rails/config/environments/test.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # The test environment is used exclusively to run your application's 5 | # test suite. You never need to work with it otherwise. Remember that 6 | # your test database is "scratch space" for the test suite and is wiped 7 | # and recreated between test runs. Don't rely on the data there! 8 | config.cache_classes = true 9 | 10 | # Do not eager load code on boot. This avoids loading your whole application 11 | # just for the purpose of running a single test. If you are using a tool that 12 | # preloads Rails for running tests, you may have to set it to true. 13 | config.eager_load = false 14 | 15 | # Configure public file server for tests with Cache-Control for performance. 16 | config.public_file_server.enabled = true 17 | config.public_file_server.headers = { 18 | 'Cache-Control' => 'public, max-age=3600' 19 | } 20 | 21 | # Show full error reports and disable caching. 22 | config.consider_all_requests_local = true 23 | config.action_controller.perform_caching = false 24 | 25 | # Raise exceptions instead of rendering exception templates. 26 | config.action_dispatch.show_exceptions = false 27 | 28 | # Disable request forgery protection in test environment. 29 | config.action_controller.allow_forgery_protection = false 30 | config.action_mailer.perform_caching = false 31 | 32 | # Tell Action Mailer not to deliver emails to the real world. 33 | # The :test delivery method accumulates sent emails in the 34 | # ActionMailer::Base.deliveries array. 35 | config.action_mailer.delivery_method = :test 36 | 37 | # Print deprecation notices to the stderr. 38 | config.active_support.deprecation = :stderr 39 | 40 | # Raises error for missing translations 41 | # config.action_view.raise_on_missing_translations = true 42 | end 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Extreme Carpaccio 2 | 3 | French version [here](./README-FR.md). 4 | 5 | Extreme Carpaccio is a coding game designed to encourage and favour incremental development and Continuous Delivery best practices. 6 | 7 | During a Extreme Carpaccio session, the facilitator uses his/her computer as a server and sends HTTP requests to participant machines (generally organised in teams). Each request is a purchasing order, like those you have when you buy something somewhere. Participants then calculate the order's total amount and send the correct response back to the server. For every correct response, the participant earns points and increases his/her score. For bad responses, penalties are charged and the participant loses points. Participants should slice (or decouple) the problem in order to deploy small chunks of the solution into production as soon as possible and then score before others. This is the purpose of this exercise: define a slicing strategy, implement, deploy, check feedback, adapt the strategy, implement, deploy... and iterate as fast as possible. **Those who don't slice and try go to production only once the whole solution is implemented risk to spend too much time before scoring, leaving the way free to other teams win.** 8 | 9 | This workshop, kata, or coding game is intented to help teams to practice concepts like Continuous Delivery, Lean Startup, eXtreme Programming, Agile Development, and more. 10 | 11 | Ready for the challenge? 12 | 13 | If you are a **participant**, go to [clients/](./clients/README.md) to get more instructions and start playing. 14 | 15 | If you are a **facilitator**, go to [server/](./server/README.md) and find out how to facilitate a session. 16 | 17 | Have fun :D 18 | 19 | ## People running Extreme Carpaccio 20 | - Find out what people are saying about Extreme Carpaccio on [Twitter](https://twitter.com/search?vertical=default&q=%22extreme%20carpaccio%22%20OR%20%22Xtreme%20carpaccio%22%20OR%20%23ExtremeCarpaccio&src=typd) 21 | -------------------------------------------------------------------------------- /server/javascripts/services/order.js: -------------------------------------------------------------------------------- 1 | var repositories = require('../repositories') 2 | var _ = require('lodash') 3 | var utils = require('../utils') 4 | var chalk = require('chalk') 5 | 6 | function OrderService (configuration) { 7 | this.countries = new repositories.Countries(configuration) 8 | } 9 | 10 | module.exports = OrderService 11 | 12 | var service = OrderService.prototype 13 | 14 | service.sendOrder = function (seller, order, cashUpdater, logError) { 15 | console.info(chalk.grey('Sending order ' + utils.stringify(order) + ' to seller ' + utils.stringify(seller))) 16 | utils.post(seller.hostname, seller.port, seller.path + '/order', order, cashUpdater, logError) 17 | } 18 | 19 | service.createOrder = function (reduction) { 20 | var items = _.random(1, 10) 21 | var prices = new Array(items) 22 | var quantities = new Array(items) 23 | var country = this.countries.randomOne() 24 | 25 | for (var item = 0; item < items; item++) { 26 | var price = _.random(1, 100, true) 27 | prices[item] = utils.fixPrecision(price, 2) 28 | quantities[item] = _.random(1, 10) 29 | } 30 | 31 | return { 32 | prices: prices, 33 | quantities: quantities, 34 | country: country, 35 | reduction: reduction.name 36 | } 37 | } 38 | 39 | service.bill = function (order, reduction) { 40 | var prices = order.prices 41 | var quantities = order.quantities 42 | var sum = quantities 43 | .map(function (q, i) { return q * prices[i] }) 44 | .reduce(function (sum, current) { return sum + current }, 0) 45 | 46 | var taxRule = this.countries.taxRule(order.country) 47 | sum = taxRule.applyTax(sum) 48 | sum = reduction.apply(sum) 49 | return { total: sum } 50 | } 51 | 52 | service.validateBill = function (bill) { 53 | if (!_.has(bill, 'total')) { 54 | throw new Error('The field "total" in the response is missing.') 55 | } 56 | 57 | if (!_.isNumber(bill.total)) { 58 | throw new Error('"Total" is not a number.') 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /clients/java/java-httpserver/src/main/java/xcarpaccio/FeedbackMessage.java: -------------------------------------------------------------------------------- 1 | package xcarpaccio; 2 | 3 | import org.codehaus.jackson.map.ObjectMapper; 4 | 5 | import java.io.IOException; 6 | 7 | public class FeedbackMessage { 8 | private final ObjectMapper objectMapper = new ObjectMapper(); 9 | 10 | private String type; 11 | private String content; 12 | 13 | // Required by Jackson 14 | private FeedbackMessage() { 15 | } 16 | 17 | public FeedbackMessage(String type, String content) { 18 | this.type = type; 19 | this.content = content; 20 | } 21 | 22 | public String getType() { 23 | return type; 24 | } 25 | 26 | public void setType(String type) { 27 | this.type = type; 28 | } 29 | 30 | public String getContent() { 31 | return content; 32 | } 33 | 34 | public void setContent(String content) { 35 | this.content = content; 36 | } 37 | 38 | public String json() throws IOException { 39 | return objectMapper.writeValueAsString(this); 40 | } 41 | 42 | @Override 43 | public boolean equals(Object o) { 44 | if (this == o) return true; 45 | if (o == null || getClass() != o.getClass()) return false; 46 | 47 | FeedbackMessage message = (FeedbackMessage) o; 48 | 49 | if (type != null ? !type.equals(message.type) : message.type != null) return false; 50 | return !(content != null ? !content.equals(message.content) : message.content != null); 51 | 52 | } 53 | 54 | @Override 55 | public int hashCode() { 56 | int result = type != null ? type.hashCode() : 0; 57 | result = 31 * result + (content != null ? content.hashCode() : 0); 58 | return result; 59 | } 60 | 61 | @Override 62 | public String toString() { 63 | return "Message{" + 64 | "type='" + type + '\'' + 65 | ", content='" + content + '\'' + 66 | '}'; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /server/bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var app = require('../app'); 8 | var debug = require('debug')('xcarpaccio:server'); 9 | var http = require('http'); 10 | 11 | /** 12 | * Get port from environment and store in Express. 13 | */ 14 | 15 | var port = normalizePort(process.env.PORT || '3000'); 16 | app.set('port', port); 17 | 18 | /** 19 | * Create HTTP server. 20 | */ 21 | 22 | var server = http.createServer(app); 23 | 24 | /** 25 | * Listen on provided port, on all network interfaces. 26 | */ 27 | 28 | server.listen(port); 29 | server.on('error', onError); 30 | server.on('listening', onListening); 31 | 32 | /** 33 | * Normalize a port into a number, string, or false. 34 | */ 35 | 36 | function normalizePort(val) { 37 | var port = parseInt(val, 10); 38 | 39 | if (isNaN(port)) { 40 | // named pipe 41 | return val; 42 | } 43 | 44 | if (port >= 0) { 45 | // port number 46 | return port; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | /** 53 | * Event listener for HTTP server "error" event. 54 | */ 55 | 56 | function onError(error) { 57 | if (error.syscall !== 'listen') { 58 | throw error; 59 | } 60 | 61 | var bind = typeof port === 'string' 62 | ? 'Pipe ' + port 63 | : 'Port ' + port 64 | 65 | // handle specific listen errors with friendly messages 66 | switch (error.code) { 67 | case 'EACCES': 68 | console.error(bind + ' requires elevated privileges'); 69 | process.exit(1); 70 | break; 71 | case 'EADDRINUSE': 72 | console.error(bind + ' is already in use'); 73 | process.exit(1); 74 | break; 75 | default: 76 | throw error; 77 | } 78 | } 79 | 80 | /** 81 | * Event listener for HTTP server "listening" event. 82 | */ 83 | 84 | function onListening() { 85 | var addr = server.address(); 86 | var bind = typeof addr === 'string' 87 | ? 'pipe ' + addr 88 | : 'port ' + addr.port; 89 | debug('Listening on ' + bind); 90 | } 91 | -------------------------------------------------------------------------------- /clients/java/java-springboot/src/test/java/xcarpaccio/WebControllerMockedServerTest.java: -------------------------------------------------------------------------------- 1 | package xcarpaccio; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.http.MediaType; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | import org.springframework.test.web.servlet.MockMvc; 11 | 12 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 13 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 14 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 15 | 16 | /** 17 | * Testing web API without the cost of starting the server but yet all the layers below 18 | * and for this using MockMvc 19 | */ 20 | @RunWith(SpringRunner.class) 21 | @SpringBootTest 22 | @AutoConfigureMockMvc 23 | public class WebControllerMockedServerTest { 24 | 25 | @Autowired 26 | private MockMvc mockMvc; 27 | 28 | @Test 29 | public void orderWithEmptyPriceListShouldReturn0() throws Exception { 30 | this.mockMvc.perform( 31 | post("/order/") 32 | .content("{\"prices\":[]}") 33 | .contentType(MediaType.APPLICATION_JSON_UTF8)) 34 | .andExpect(status().isOk()) 35 | .andExpect(content().json("{\"total\":0}")) 36 | ; 37 | } 38 | 39 | @Test 40 | public void aNominalTest() throws Exception { 41 | this.mockMvc.perform( 42 | post("/order/") 43 | .content("{\"prices\":[1]}") 44 | .contentType(MediaType.APPLICATION_JSON_UTF8)) 45 | // Throws a 404 for now, to avoid penalty 46 | .andExpect(status().isNotFound()); 47 | } 48 | } -------------------------------------------------------------------------------- /clients/java/java-httpserver/src/test/java/xcarpaccio/MyHttpServerTest.java: -------------------------------------------------------------------------------- 1 | package xcarpaccio; 2 | 3 | import org.junit.After; 4 | import org.junit.Before; 5 | import org.junit.Ignore; 6 | import org.junit.Test; 7 | 8 | import static org.assertj.core.api.Assertions.assertThat; 9 | import static org.mockito.BDDMockito.then; 10 | import static org.mockito.Mockito.mock; 11 | 12 | public class MyHttpServerTest extends AbstractHttpServerTest 13 | { 14 | private static final int TEST_PORT = 8001; 15 | private static final String LOCALHOST = "http://localhost:" + TEST_PORT; 16 | 17 | private MyHttpServer server; 18 | private Logger logger; 19 | 20 | @Before 21 | public void startServer() throws Exception { 22 | logger = mock(Logger.class); 23 | server = new MyHttpServer(TEST_PORT, logger); 24 | server.start(); 25 | } 26 | 27 | @After 28 | public void stopServer() { 29 | server.shutdown(); 30 | } 31 | 32 | @Test 33 | public void should_respond_pong_when_receive_ping() throws Exception { 34 | assertThat(get(LOCALHOST + "/ping")).isEqualTo("pong"); 35 | } 36 | 37 | @Test 38 | public void should_print_received_message_via_post() throws Exception { 39 | post(LOCALHOST + "/feedback", new FeedbackMessage("info", "test").json()); 40 | 41 | then(logger).should().log("info: test"); 42 | } 43 | 44 | @Test 45 | @Ignore 46 | public void should_deserialize_JSON_order_and_render_total() throws Exception { 47 | String body = post(LOCALHOST + "/order", "{\"prices\":[3.5],\"quantities\":[2],\"country\":\"ES\",\"reduction\":\"STANDARD\"}"); 48 | 49 | assertThat(body).isEqualTo("{\"total\":7.0}"); 50 | } 51 | 52 | @Test 53 | @Ignore 54 | public void should_reject_an_order() throws Exception { 55 | String body = post(LOCALHOST + "/order", "{\"prices\":[3.5],\"quantities\":[2],\"country\":\"ES\",\"reduction\":\"STANDARD\"}"); 56 | 57 | assertThat(body).isEqualTo(""); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /server/specs/utils_spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var http = require('http'); 4 | 5 | var utils = require('../javascripts/utils'); 6 | 7 | describe('Utils', function() { 8 | 9 | it('should fix precision for numbers', function() { 10 | expect(utils.fixPrecision(1, 2)).toBe(1.00); 11 | expect(utils.fixPrecision(1.234, 2)).toBe(1.23); 12 | }); 13 | 14 | it('should parse a string into a json object', function() { 15 | expect(utils.jsonify('{"name": "Bob"}')).toEqual({name: 'Bob'}) 16 | }); 17 | 18 | it('should not parse a string but return an empty object when input is not a valid json object', function() { 19 | expect(function(){utils.jsonify('not valid json object')}).toThrow(); 20 | expect(function(){utils.jsonify('')}).toThrow(); 21 | expect(function(){utils.jsonify(undefined)}).toThrow(); 22 | }); 23 | 24 | it('should send post request to someone else', function() { 25 | var fakeRequest = { 26 | write: function() {}, 27 | on: function() {}, 28 | end: function() {} 29 | }; 30 | spyOn(http, 'request').andReturn(fakeRequest); 31 | spyOn(fakeRequest, 'write'); 32 | spyOn(fakeRequest, 'end'); 33 | var body = {content: 'some content'}; 34 | var callback = function() {}; 35 | 36 | utils.post('localhost', '3000', '/path', body, callback); 37 | 38 | var bodyStringified = utils.stringify(body); 39 | expect(http.request).toHaveBeenCalledWith({ 40 | hostname : 'localhost', 41 | port : '3000', 42 | path : '/path', 43 | method : 'POST', 44 | headers : { 45 | 'Content-Type' : 'application/json', 46 | 'Accept' : 'application/json', 47 | 'Content-Length' : bodyStringified.length 48 | } 49 | }, callback); 50 | expect(fakeRequest.write).toHaveBeenCalledWith(bodyStringified); 51 | expect(fakeRequest.end).toHaveBeenCalled(); 52 | }); 53 | }); -------------------------------------------------------------------------------- /clients/java/java-springboot/src/test/java/xcarpaccio/WebControllerServerTest.java: -------------------------------------------------------------------------------- 1 | package xcarpaccio; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.test.context.SpringBootTest; 7 | import org.springframework.boot.test.web.client.TestRestTemplate; 8 | import org.springframework.boot.web.server.LocalServerPort; 9 | import org.springframework.http.HttpStatus; 10 | import org.springframework.http.ResponseEntity; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | 13 | import static org.junit.Assert.assertEquals; 14 | 15 | /** 16 | * Testing web API, starting the server 17 | */ 18 | @RunWith(SpringRunner.class) 19 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 20 | public class WebControllerServerTest { 21 | 22 | @LocalServerPort 23 | private int port; 24 | 25 | @Autowired 26 | private TestRestTemplate restTemplate; 27 | 28 | @Test 29 | public void orderWithEmptyPriceListShouldReturn0() { 30 | TestRestTemplate testRestTemplate = new TestRestTemplate(); 31 | Order order = new Order(); 32 | order.prices = new Double[] {}; 33 | ResponseEntity response = testRestTemplate. 34 | postForEntity("http://localhost:" + this.port + "/order", order, Amount.class); 35 | assertEquals(HttpStatus.OK, response.getStatusCode()); 36 | assertEquals(new Double(0.0), response.getBody().total); 37 | } 38 | 39 | @Test 40 | public void aNominalTest() { 41 | TestRestTemplate testRestTemplate = new TestRestTemplate(); 42 | Order order = new Order(); 43 | order.prices = new Double[] {0.0}; 44 | ResponseEntity response = testRestTemplate. 45 | postForEntity("http://localhost:" + this.port + "/order", order, Amount.class); 46 | // Throws a 404 for now, to avoid penalty 47 | assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); 48 | } 49 | } 50 | --------------------------------------------------------------------------------