diff --git a/bin/silex-petstore-server.sh b/bin/silex-petstore-server.sh index 5ead9db0002..ffa030b88c3 100755 --- a/bin/silex-petstore-server.sh +++ b/bin/silex-petstore-server.sh @@ -26,6 +26,6 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" -ags="$@ generate -t modules/swagger-codegen/src/main/resources/silex -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l silex -o samples/client/petstore/silex" +ags="$@ generate -t modules/swagger-codegen/src/main/resources/silex -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l silex -o samples/server/petstore/silex" java $JAVA_OPTS -jar $executable $ags diff --git a/bin/sinatra-petstore-server.sh b/bin/sinatra-petstore-server.sh new file mode 100755 index 00000000000..4f7e19cee39 --- /dev/null +++ b/bin/sinatra-petstore-server.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +SCRIPT="$0" + +while [ -h "$SCRIPT" ] ; do + ls=`ls -ld "$SCRIPT"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + SCRIPT="$link" + else + SCRIPT=`dirname "$SCRIPT"`/"$link" + fi +done + +if [ ! -d "${APP_DIR}" ]; then + APP_DIR=`dirname "$SCRIPT"`/.. + APP_DIR=`cd "${APP_DIR}"; pwd` +fi + +executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar" + +if [ ! -f "$executable" ] +then + mvn clean package +fi + +# if you've executed sbt assembly previously it will use that instead. +export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" +ags="$@ generate -t modules/swagger-codegen/src/main/resources/sinatra -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l sinatra -o samples/server/petstore/sinatra" + +java $JAVA_OPTS -jar $executable $ags diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SinatraServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SinatraServerCodegen.java new file mode 100644 index 00000000000..318bf03130d --- /dev/null +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SinatraServerCodegen.java @@ -0,0 +1,215 @@ +package io.swagger.codegen.languages; + +import io.swagger.codegen.CliOption; +import io.swagger.codegen.CodegenConfig; +import io.swagger.codegen.CodegenType; +import io.swagger.codegen.DefaultCodegen; +import io.swagger.codegen.SupportingFile; +import io.swagger.models.properties.ArrayProperty; +import io.swagger.models.properties.MapProperty; +import io.swagger.models.properties.Property; + +import java.io.File; +import java.util.Arrays; +import java.util.HashSet; + +public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfig { + protected String gemName = null; + protected String moduleName = null; + protected String gemVersion = "1.0.0"; + protected String libFolder = "lib"; + + public SinatraServerCodegen() { + super(); + apiPackage = "lib"; + outputFolder = "generated-code" + File.separator + "sinatra"; + + // no model + modelTemplateFiles.clear(); + apiTemplateFiles.put("api.mustache", ".rb"); + templateDir = "sinatra"; + + typeMapping.clear(); + languageSpecificPrimitives.clear(); + + reservedWords = new HashSet( + Arrays.asList( + "__FILE__", "and", "def", "end", "in", "or", "self", "unless", "__LINE__", + "begin", "defined?", "ensure", "module", "redo", "super", "until", "BEGIN", + "break", "do", "false", "next", "rescue", "then", "when", "END", "case", + "else", "for", "nil", "retry", "true", "while", "alias", "class", "elsif", + "if", "not", "return", "undef", "yield") + ); + + languageSpecificPrimitives.add("int"); + languageSpecificPrimitives.add("array"); + languageSpecificPrimitives.add("map"); + languageSpecificPrimitives.add("string"); + languageSpecificPrimitives.add("DateTime"); + + typeMapping.put("long", "int"); + typeMapping.put("integer", "int"); + typeMapping.put("Array", "array"); + typeMapping.put("String", "string"); + typeMapping.put("List", "array"); + typeMapping.put("map", "map"); + + // remove modelPackage and apiPackage added by default + cliOptions.clear(); + } + + @Override + public void processOpts() { + super.processOpts(); + + // use constant model/api package (folder path) + //setModelPackage("models"); + setApiPackage("api"); + + supportingFiles.add(new SupportingFile("my_app.mustache", "", "my_app.rb")); + supportingFiles.add(new SupportingFile("Swaggering.rb", libFolder, "Swaggering.rb")); + supportingFiles.add(new SupportingFile("config.ru", "", "config.rb")); + supportingFiles.add(new SupportingFile("Gemfile", "", "Gemfile")); + supportingFiles.add(new SupportingFile("README.md", "", "README.md")); + } + + public CodegenType getTag() { + return CodegenType.CLIENT; + } + + public String getName() { + return "sinatra"; + } + + public String getHelp() { + return "Generates a Sinatra server library."; + } + + @Override + public String escapeReservedWord(String name) { + return "_" + name; + } + + @Override + public String apiFileFolder() { + return outputFolder + File.separator + apiPackage.replace("/", File.separator); + } + + @Override + public String getTypeDeclaration(Property p) { + if (p instanceof ArrayProperty) { + ArrayProperty ap = (ArrayProperty) p; + Property inner = ap.getItems(); + return getSwaggerType(p) + "[" + getTypeDeclaration(inner) + "]"; + } else if (p instanceof MapProperty) { + MapProperty mp = (MapProperty) p; + Property inner = mp.getAdditionalProperties(); + return getSwaggerType(p) + "[string," + getTypeDeclaration(inner) + "]"; + } + return super.getTypeDeclaration(p); + } + + @Override + public String getSwaggerType(Property p) { + String swaggerType = super.getSwaggerType(p); + String type = null; + if (typeMapping.containsKey(swaggerType)) { + type = typeMapping.get(swaggerType); + if (languageSpecificPrimitives.contains(type)) { + return type; + } + } else { + type = swaggerType; + } + if (type == null) { + return null; + } + return type; + } + + public String toDefaultValue(Property p) { + return "null"; + } + + @Override + public String toVarName(String name) { + // replace - with _ e.g. created-at => created_at + name = name.replaceAll("-", "_"); + + // if it's all uppper case, convert to lower case + if (name.matches("^[A-Z_]*$")) { + name = name.toLowerCase(); + } + + // camelize (lower first character) the variable name + // petId => pet_id + name = underscore(name); + + // for reserved word or word starting with number, append _ + if (reservedWords.contains(name) || name.matches("^\\d.*")) { + name = escapeReservedWord(name); + } + + return name; + } + + @Override + public String toParamName(String name) { + // should be the same as variable name + return toVarName(name); + } + + @Override + public String toModelName(String name) { + // model name cannot use reserved keyword, e.g. return + if (reservedWords.contains(name)) { + throw new RuntimeException(name + " (reserved word) cannot be used as a model name"); + } + + // camelize the model name + // phone_number => PhoneNumber + return camelize(name); + } + + @Override + public String toModelFilename(String name) { + // model name cannot use reserved keyword, e.g. return + if (reservedWords.contains(name)) { + throw new RuntimeException(name + " (reserved word) cannot be used as a model name"); + } + + // underscore the model file name + // PhoneNumber.rb => phone_number.rb + return underscore(name); + } + + @Override + public String toApiFilename(String name) { + // replace - with _ e.g. created-at => created_at + name = name.replaceAll("-", "_"); + + // e.g. PhoneNumberApi.rb => phone_number_api.rb + return underscore(name) + "_api"; + } + + @Override + public String toApiName(String name) { + if (name.length() == 0) { + return "DefaultApi"; + } + // e.g. phone_number_api => PhoneNumberApi + return camelize(name) + "Api"; + } + + @Override + public String toOperationId(String operationId) { + // method name cannot use reserved keyword, e.g. return + if (reservedWords.contains(operationId)) { + throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); + } + + return underscore(operationId); + } + + +} diff --git a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig index ce3edfd1359..86cf9ef6013 100644 --- a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig +++ b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig @@ -15,6 +15,7 @@ io.swagger.codegen.languages.RubyClientCodegen io.swagger.codegen.languages.ScalaClientCodegen io.swagger.codegen.languages.ScalatraServerCodegen io.swagger.codegen.languages.SilexServerCodegen +io.swagger.codegen.languages.SinatraServerCodegen io.swagger.codegen.languages.SpringMVCServerCodegen io.swagger.codegen.languages.StaticDocCodegen io.swagger.codegen.languages.StaticHtmlGenerator diff --git a/modules/swagger-codegen/src/main/resources/sinatra/Gemfile b/modules/swagger-codegen/src/main/resources/sinatra/Gemfile new file mode 100644 index 00000000000..be9c3168ea6 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/sinatra/Gemfile @@ -0,0 +1,4 @@ +source 'https://rubygems.org' + +gem "sinatra" +gem "sinatra-cross_origin" \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/sinatra/README.md b/modules/swagger-codegen/src/main/resources/sinatra/README.md new file mode 100644 index 00000000000..23c501353da --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/sinatra/README.md @@ -0,0 +1,29 @@ +# Swagger for Sinatra + +## Overview +This is a project to provide Swagger support inside the [Sinatra](http://www.sinatrarb.com/) framework. You can find +out more about both the spec and the framework at http://swagger.wordnik.com. For more information about +Wordnik's APIs, please visit http://developer.wordnik.com. + +## Prerequisites +You need to install ruby 1.9.3 and the following gems: + +``` +sinatra +sinatra-cross_origin +``` + +## Getting started +This sample was generated with the [swagger-codegen](https://github.com/wordnik/swagger-codegen) project. + +``` +rackup -p 4567 config.ru +``` + +In your [swagger ui](https://github.com/wordnik/swagger-ui), put in the following URL: + +``` +http://localhost:4567/resources.json +``` + +Voila! diff --git a/modules/swagger-codegen/src/main/resources/sinatra/Swaggering.rb b/modules/swagger-codegen/src/main/resources/sinatra/Swaggering.rb new file mode 100644 index 00000000000..79aca1da2c9 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/sinatra/Swaggering.rb @@ -0,0 +1,154 @@ +require 'json' +require 'sinatra/base' +require 'sinatra/cross_origin' + +class Configuration + attr_accessor :base_path, :api_version, :swagger_version, :format_specifier + + def initialize + @api_version = '1.0' + @base_path = 'http://localhost:4567' + @swagger_version = '1.1' + @format_specifier = ".json" + end +end + +class Swaggering < Sinatra::Base + register Sinatra::CrossOrigin + + @@routes = {} + @@configuration = Configuration.new + + attr_accessor :configuration + + def self.configure + get("/resources" + @@configuration.format_specifier) { + cross_origin + Swaggering.to_resource_listing + } + @@configuration ||= Configuration.new + yield(@@configuration) if block_given? + end + + def self.add_route(method, path, swag={}, opts={}, &block) + fullPath = swag["resourcePath"].to_s + @@configuration.format_specifier + path + + accepted = case method + when 'get' + get(fullPath, opts, &block) + true + when 'post' + post(fullPath, opts, &block) + true + when 'delete' + delete(fullPath, opts, &block) + true + when 'put' + put(fullPath, opts, &block) + true + else + false + end + + if accepted then + resourcePath = swag["resourcePath"].to_s + ops = @@routes[resourcePath] + if ops.nil? + ops = Array.new + @@routes.merge!(resourcePath => ops) + + get(resourcePath + @@configuration.format_specifier) do + cross_origin + Swaggering.to_api(resourcePath) + end + end + + swag.merge!("httpMethod" => method.to_s.upcase) + ops.push(swag) + end + end + + def self.to_resource_listing + apis = Array.new + (@@routes.keys).each do |key| + api = { + "path" => (key + ".{format}"), + "description" => "no description" + } + apis.push api + end + + resource = { + "apiVersion" => @@configuration.api_version, + "swaggerVersion" => @@configuration.swagger_version, + "apis" => apis + } + + resource.to_json + end + + def self.to_api(resourcePath) + apis = {} + models = [] + + @@routes[resourcePath].each do |route| + endpoint = route["endpoint"].gsub(/:(\w+)(\/?)/,'{\1}\2') + path = (resourcePath + ".{format}" + endpoint) + api = apis[path] + if api.nil? + api = {"path" => path, "description" => "description", "operations" => []} + apis.merge!(path => api) + end + + parameters = route["parameters"] + + unless parameters.nil? then + parameters.each do |param| + av_string = param["allowableValues"] + unless av_string.nil? + if av_string.count('[') > 0 + pattern = /^([A-Z]*)\[(.*)\]/ + match = pattern.match av_string + case match.to_a[1] + when "LIST" + allowables = match.to_a[2].split(',') + param["allowableValues"] = { + "valueType" => "LIST", + "values" => allowables + } + when "RANGE" + allowables = match.to_a[2].split(',') + param["allowableValues"] = { + "valueType" => "RANGE", + "min" => allowables[0], + "max" => allowables[1] + } + end + end + end + end + end + + op = { + "httpMethod" => route["httpMethod"], + "description" => route["summary"], + "responseClass" => route["responseClass"], + "notes" => route["notes"], + "nickname" => route["nickname"], + "summary" => route["summary"], + "parameters" => route["parameters"] + } + api["operations"].push(op) + end + + api_listing = { + "apiVersion" => @@configuration.api_version, + "swaggerVersion" => @@configuration.swagger_version, + "basePath" => @@configuration.base_path, + "resourcePath" => resourcePath, + "apis" => apis.values, + "models" => models + } + api_listing.to_json + end +end diff --git a/modules/swagger-codegen/src/main/resources/sinatra/api.mustache b/modules/swagger-codegen/src/main/resources/sinatra/api.mustache new file mode 100644 index 00000000000..cfeae19de7a --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/sinatra/api.mustache @@ -0,0 +1,57 @@ +require 'json' + +{{#operations}} +{{#operation}} + +MyApp.add_route('{{httpMethod}}', '{{path}}', { + "resourcePath" => "/{{baseName}}", + "summary" => "{{{summary}}}", + "nickname" => "{{nickname}}", + "responseClass" => "{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}void{{/returnType}}", + "endpoint" => "{{path}}", + "notes" => "{{{notes}}}", + "parameters" => [ + {{#queryParams}} + { + "name" => "{{paramName}}", + "description" => "{{description}}", + "dataType" => "{{swaggerDataType}}", + "paramType" => "query", + "allowMultiple" => {{allowMultiple}}, + "allowableValues" => "{{allowableValues}}", + {{#defaultValue}}"defaultValue" => {{{defaultValue}}}{{/defaultValue}} + }, + {{/queryParams}} + {{#pathParams}} + { + "name" => "{{paramName}}", + "description" => "{{description}}", + "dataType" => "{{swaggerDataType}}", + "paramType" => "path", + }, + {{/pathParams}} + {{#headerParams}} + { + "name" => "{{paramName}}", + "description" => "{{description}}", + "dataType" => "{{swaggerDataType}}", + "paramType" => "header", + }, + {{/headerParams}} + {{#bodyParams}} + { + "name" => "body", + "description" => "{{description}}", + "dataType" => "{{swaggerDataType}}", + "paramType" => "body", + } + {{/bodyParams}} + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + +{{/operation}} +{{/operations}} diff --git a/modules/swagger-codegen/src/main/resources/sinatra/config.ru b/modules/swagger-codegen/src/main/resources/sinatra/config.ru new file mode 100644 index 00000000000..395d0587123 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/sinatra/config.ru @@ -0,0 +1,2 @@ +require './my_app' +run MyApp diff --git a/modules/swagger-codegen/src/main/resources/sinatra/my_app.mustache b/modules/swagger-codegen/src/main/resources/sinatra/my_app.mustache new file mode 100644 index 00000000000..72b5267a140 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/sinatra/my_app.mustache @@ -0,0 +1,12 @@ +require './lib/swaggering' + +# only need to extend if you want special configuration! +class MyApp < Swaggering + self.configure do |config| + config.api_version = '0.2' + end +end + +{{#apis}} +require './lib/{{className}}.rb' +{{/apis}} \ No newline at end of file diff --git a/samples/client/petstore/silex/SwaggerServer/.htaccess b/samples/client/petstore/silex/SwaggerServer/.htaccess deleted file mode 100644 index e47b5fb8a0c..00000000000 --- a/samples/client/petstore/silex/SwaggerServer/.htaccess +++ /dev/null @@ -1,5 +0,0 @@ - - RewriteEngine On - RewriteCond %{REQUEST_FILENAME} !-f - RewriteRule ^(.*)$ index.php?_url=/$1 [QSA,L] - \ No newline at end of file diff --git a/samples/client/petstore/silex/SwaggerServer/README.md b/samples/client/petstore/silex/SwaggerServer/README.md deleted file mode 100644 index 9f35636b3f8..00000000000 --- a/samples/client/petstore/silex/SwaggerServer/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Swagger generated server - -## Overview -This server was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. By using the -[swagger-spec](https://github.com/swagger-api/swagger-core/wiki) from a remote server, you can easily generate a server stub. This -is an example of building a PHP server. - -This example uses the [Silex](http://silex.sensiolabs.org/) micro-framework. To see how to make this your own, please take a look at the template here: - -[TEMPLATES](https://github.com/swagger-api/swagger-codegen/tree/master/modules/swagger-codegen/src/main/resources/silex/) diff --git a/samples/client/petstore/silex/SwaggerServer/composer.json b/samples/client/petstore/silex/SwaggerServer/composer.json deleted file mode 100644 index 466cd3fbc77..00000000000 --- a/samples/client/petstore/silex/SwaggerServer/composer.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "require": { - "silex/silex": "~1.2" - } -} \ No newline at end of file diff --git a/samples/client/petstore/silex/SwaggerServer/index.php b/samples/client/petstore/silex/SwaggerServer/index.php deleted file mode 100644 index 1526f3cb8f3..00000000000 --- a/samples/client/petstore/silex/SwaggerServer/index.php +++ /dev/null @@ -1,184 +0,0 @@ -POST('/user', function(Application $app, Request $request) { - - - return new Response('How about implementing createUser as a POST method ?'); - }); - - - -$app->POST('/user/createWithArray', function(Application $app, Request $request) { - - - return new Response('How about implementing createUsersWithArrayInput as a POST method ?'); - }); - - - -$app->POST('/user/createWithList', function(Application $app, Request $request) { - - - return new Response('How about implementing createUsersWithListInput as a POST method ?'); - }); - - - -$app->GET('/user/login', function(Application $app, Request $request) { - $username = $request->get('username'); $password = $request->get('password'); - - return new Response('How about implementing loginUser as a GET method ?'); - }); - - - -$app->GET('/user/logout', function(Application $app, Request $request) { - - - return new Response('How about implementing logoutUser as a GET method ?'); - }); - - - -$app->GET('/user/{username}', function(Application $app, Request $request, $username) { - - - return new Response('How about implementing getUserByName as a GET method ?'); - }); - - - -$app->PUT('/user/{username}', function(Application $app, Request $request, $username) { - - - return new Response('How about implementing updateUser as a PUT method ?'); - }); - - - -$app->DELETE('/user/{username}', function(Application $app, Request $request, $username) { - - - return new Response('How about implementing deleteUser as a DELETE method ?'); - }); - - - - - - - -$app->PUT('/pet', function(Application $app, Request $request) { - - - return new Response('How about implementing updatePet as a PUT method ?'); - }); - - - -$app->POST('/pet', function(Application $app, Request $request) { - - - return new Response('How about implementing addPet as a POST method ?'); - }); - - - -$app->GET('/pet/findByStatus', function(Application $app, Request $request) { - $status = $request->get('status'); - - return new Response('How about implementing findPetsByStatus as a GET method ?'); - }); - - - -$app->GET('/pet/findByTags', function(Application $app, Request $request) { - $tags = $request->get('tags'); - - return new Response('How about implementing findPetsByTags as a GET method ?'); - }); - - - -$app->GET('/pet/{petId}', function(Application $app, Request $request, $pet_id) { - - - return new Response('How about implementing getPetById as a GET method ?'); - }); - - - -$app->POST('/pet/{petId}', function(Application $app, Request $request, $pet_id) { - - $name = $request->get('name'); $status = $request->get('status'); - return new Response('How about implementing updatePetWithForm as a POST method ?'); - }); - - - -$app->DELETE('/pet/{petId}', function(Application $app, Request $request, $pet_id) { - - - return new Response('How about implementing deletePet as a DELETE method ?'); - }); - - - -$app->POST('/pet/{petId}/uploadImage', function(Application $app, Request $request, $pet_id) { - - $additional_metadata = $request->get('additional_metadata'); $file = $request->get('file'); - return new Response('How about implementing uploadFile as a POST method ?'); - }); - - - - - - - -$app->GET('/store/inventory', function(Application $app, Request $request) { - - - return new Response('How about implementing getInventory as a GET method ?'); - }); - - - -$app->POST('/store/order', function(Application $app, Request $request) { - - - return new Response('How about implementing placeOrder as a POST method ?'); - }); - - - -$app->GET('/store/order/{orderId}', function(Application $app, Request $request, $order_id) { - - - return new Response('How about implementing getOrderById as a GET method ?'); - }); - - - -$app->DELETE('/store/order/{orderId}', function(Application $app, Request $request, $order_id) { - - - return new Response('How about implementing deleteOrder as a DELETE method ?'); - }); - - - - - -$app->run(); diff --git a/samples/client/petstore/silex/silex/.htaccess b/samples/client/petstore/silex/silex/.htaccess deleted file mode 100644 index e47b5fb8a0c..00000000000 --- a/samples/client/petstore/silex/silex/.htaccess +++ /dev/null @@ -1,5 +0,0 @@ - - RewriteEngine On - RewriteCond %{REQUEST_FILENAME} !-f - RewriteRule ^(.*)$ index.php?_url=/$1 [QSA,L] - \ No newline at end of file diff --git a/samples/client/petstore/silex/silex/README.md b/samples/client/petstore/silex/silex/README.md deleted file mode 100644 index 9f35636b3f8..00000000000 --- a/samples/client/petstore/silex/silex/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Swagger generated server - -## Overview -This server was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. By using the -[swagger-spec](https://github.com/swagger-api/swagger-core/wiki) from a remote server, you can easily generate a server stub. This -is an example of building a PHP server. - -This example uses the [Silex](http://silex.sensiolabs.org/) micro-framework. To see how to make this your own, please take a look at the template here: - -[TEMPLATES](https://github.com/swagger-api/swagger-codegen/tree/master/modules/swagger-codegen/src/main/resources/silex/) diff --git a/samples/client/petstore/silex/silex/composer.json b/samples/client/petstore/silex/silex/composer.json deleted file mode 100644 index 466cd3fbc77..00000000000 --- a/samples/client/petstore/silex/silex/composer.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "require": { - "silex/silex": "~1.2" - } -} \ No newline at end of file diff --git a/samples/client/petstore/silex/silex/index.php b/samples/client/petstore/silex/silex/index.php deleted file mode 100644 index 1526f3cb8f3..00000000000 --- a/samples/client/petstore/silex/silex/index.php +++ /dev/null @@ -1,184 +0,0 @@ -POST('/user', function(Application $app, Request $request) { - - - return new Response('How about implementing createUser as a POST method ?'); - }); - - - -$app->POST('/user/createWithArray', function(Application $app, Request $request) { - - - return new Response('How about implementing createUsersWithArrayInput as a POST method ?'); - }); - - - -$app->POST('/user/createWithList', function(Application $app, Request $request) { - - - return new Response('How about implementing createUsersWithListInput as a POST method ?'); - }); - - - -$app->GET('/user/login', function(Application $app, Request $request) { - $username = $request->get('username'); $password = $request->get('password'); - - return new Response('How about implementing loginUser as a GET method ?'); - }); - - - -$app->GET('/user/logout', function(Application $app, Request $request) { - - - return new Response('How about implementing logoutUser as a GET method ?'); - }); - - - -$app->GET('/user/{username}', function(Application $app, Request $request, $username) { - - - return new Response('How about implementing getUserByName as a GET method ?'); - }); - - - -$app->PUT('/user/{username}', function(Application $app, Request $request, $username) { - - - return new Response('How about implementing updateUser as a PUT method ?'); - }); - - - -$app->DELETE('/user/{username}', function(Application $app, Request $request, $username) { - - - return new Response('How about implementing deleteUser as a DELETE method ?'); - }); - - - - - - - -$app->PUT('/pet', function(Application $app, Request $request) { - - - return new Response('How about implementing updatePet as a PUT method ?'); - }); - - - -$app->POST('/pet', function(Application $app, Request $request) { - - - return new Response('How about implementing addPet as a POST method ?'); - }); - - - -$app->GET('/pet/findByStatus', function(Application $app, Request $request) { - $status = $request->get('status'); - - return new Response('How about implementing findPetsByStatus as a GET method ?'); - }); - - - -$app->GET('/pet/findByTags', function(Application $app, Request $request) { - $tags = $request->get('tags'); - - return new Response('How about implementing findPetsByTags as a GET method ?'); - }); - - - -$app->GET('/pet/{petId}', function(Application $app, Request $request, $pet_id) { - - - return new Response('How about implementing getPetById as a GET method ?'); - }); - - - -$app->POST('/pet/{petId}', function(Application $app, Request $request, $pet_id) { - - $name = $request->get('name'); $status = $request->get('status'); - return new Response('How about implementing updatePetWithForm as a POST method ?'); - }); - - - -$app->DELETE('/pet/{petId}', function(Application $app, Request $request, $pet_id) { - - - return new Response('How about implementing deletePet as a DELETE method ?'); - }); - - - -$app->POST('/pet/{petId}/uploadImage', function(Application $app, Request $request, $pet_id) { - - $additional_metadata = $request->get('additional_metadata'); $file = $request->get('file'); - return new Response('How about implementing uploadFile as a POST method ?'); - }); - - - - - - - -$app->GET('/store/inventory', function(Application $app, Request $request) { - - - return new Response('How about implementing getInventory as a GET method ?'); - }); - - - -$app->POST('/store/order', function(Application $app, Request $request) { - - - return new Response('How about implementing placeOrder as a POST method ?'); - }); - - - -$app->GET('/store/order/{orderId}', function(Application $app, Request $request, $order_id) { - - - return new Response('How about implementing getOrderById as a GET method ?'); - }); - - - -$app->DELETE('/store/order/{orderId}', function(Application $app, Request $request, $order_id) { - - - return new Response('How about implementing deleteOrder as a DELETE method ?'); - }); - - - - - -$app->run(); diff --git a/samples/server/petstore/sinatra/Gemfile b/samples/server/petstore/sinatra/Gemfile new file mode 100644 index 00000000000..be9c3168ea6 --- /dev/null +++ b/samples/server/petstore/sinatra/Gemfile @@ -0,0 +1,4 @@ +source 'https://rubygems.org' + +gem "sinatra" +gem "sinatra-cross_origin" \ No newline at end of file diff --git a/samples/server/petstore/sinatra/README.md b/samples/server/petstore/sinatra/README.md new file mode 100644 index 00000000000..23c501353da --- /dev/null +++ b/samples/server/petstore/sinatra/README.md @@ -0,0 +1,29 @@ +# Swagger for Sinatra + +## Overview +This is a project to provide Swagger support inside the [Sinatra](http://www.sinatrarb.com/) framework. You can find +out more about both the spec and the framework at http://swagger.wordnik.com. For more information about +Wordnik's APIs, please visit http://developer.wordnik.com. + +## Prerequisites +You need to install ruby 1.9.3 and the following gems: + +``` +sinatra +sinatra-cross_origin +``` + +## Getting started +This sample was generated with the [swagger-codegen](https://github.com/wordnik/swagger-codegen) project. + +``` +rackup -p 4567 config.ru +``` + +In your [swagger ui](https://github.com/wordnik/swagger-ui), put in the following URL: + +``` +http://localhost:4567/resources.json +``` + +Voila! diff --git a/samples/server/petstore/sinatra/api/pet_api.rb b/samples/server/petstore/sinatra/api/pet_api.rb new file mode 100644 index 00000000000..2fdc1f2a6e6 --- /dev/null +++ b/samples/server/petstore/sinatra/api/pet_api.rb @@ -0,0 +1,231 @@ +require 'json' + + +MyApp.add_route('PUT', '/pet', { + "resourcePath" => "/Pet", + "summary" => "Update an existing pet", + "nickname" => "update_pet", + "responseClass" => "void", + "endpoint" => "/pet", + "notes" => "", + "parameters" => [ + + + + + { + "name" => "body", + "description" => "Pet object that needs to be added to the store", + "dataType" => "", + "paramType" => "body", + } + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('POST', '/pet', { + "resourcePath" => "/Pet", + "summary" => "Add a new pet to the store", + "nickname" => "add_pet", + "responseClass" => "void", + "endpoint" => "/pet", + "notes" => "", + "parameters" => [ + + + + + { + "name" => "body", + "description" => "Pet object that needs to be added to the store", + "dataType" => "", + "paramType" => "body", + } + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('GET', '/pet/findByStatus', { + "resourcePath" => "/Pet", + "summary" => "Finds Pets by status", + "nickname" => "find_pets_by_status", + "responseClass" => "array[Pet]", + "endpoint" => "/pet/findByStatus", + "notes" => "Multiple status values can be provided with comma seperated strings", + "parameters" => [ + + { + "name" => "status", + "description" => "Status values that need to be considered for filter", + "dataType" => "", + "paramType" => "query", + "allowMultiple" => , + "allowableValues" => "", + "defaultValue" => available + }, + + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('GET', '/pet/findByTags', { + "resourcePath" => "/Pet", + "summary" => "Finds Pets by tags", + "nickname" => "find_pets_by_tags", + "responseClass" => "array[Pet]", + "endpoint" => "/pet/findByTags", + "notes" => "Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing.", + "parameters" => [ + + { + "name" => "tags", + "description" => "Tags to filter by", + "dataType" => "", + "paramType" => "query", + "allowMultiple" => , + "allowableValues" => "", + + }, + + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('GET', '/pet/{petId}', { + "resourcePath" => "/Pet", + "summary" => "Find pet by ID", + "nickname" => "get_pet_by_id", + "responseClass" => "Pet", + "endpoint" => "/pet/{petId}", + "notes" => "Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API error conditions", + "parameters" => [ + + + { + "name" => "pet_id", + "description" => "ID of pet that needs to be fetched", + "dataType" => "", + "paramType" => "path", + }, + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('POST', '/pet/{petId}', { + "resourcePath" => "/Pet", + "summary" => "Updates a pet in the store with form data", + "nickname" => "update_pet_with_form", + "responseClass" => "void", + "endpoint" => "/pet/{petId}", + "notes" => "", + "parameters" => [ + + + { + "name" => "pet_id", + "description" => "ID of pet that needs to be updated", + "dataType" => "", + "paramType" => "path", + }, + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('DELETE', '/pet/{petId}', { + "resourcePath" => "/Pet", + "summary" => "Deletes a pet", + "nickname" => "delete_pet", + "responseClass" => "void", + "endpoint" => "/pet/{petId}", + "notes" => "", + "parameters" => [ + + + { + "name" => "pet_id", + "description" => "Pet id to delete", + "dataType" => "", + "paramType" => "path", + }, + + + { + "name" => "api_key", + "description" => "", + "dataType" => "", + "paramType" => "header", + }, + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('POST', '/pet/{petId}/uploadImage', { + "resourcePath" => "/Pet", + "summary" => "uploads an image", + "nickname" => "upload_file", + "responseClass" => "void", + "endpoint" => "/pet/{petId}/uploadImage", + "notes" => "", + "parameters" => [ + + + { + "name" => "pet_id", + "description" => "ID of pet to update", + "dataType" => "", + "paramType" => "path", + }, + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + diff --git a/samples/server/petstore/sinatra/api/store_api.rb b/samples/server/petstore/sinatra/api/store_api.rb new file mode 100644 index 00000000000..245ae23bff7 --- /dev/null +++ b/samples/server/petstore/sinatra/api/store_api.rb @@ -0,0 +1,103 @@ +require 'json' + + +MyApp.add_route('GET', '/store/inventory', { + "resourcePath" => "/Store", + "summary" => "Returns pet inventories by status", + "nickname" => "get_inventory", + "responseClass" => "map[string,int]", + "endpoint" => "/store/inventory", + "notes" => "Returns a map of status codes to quantities", + "parameters" => [ + + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('POST', '/store/order', { + "resourcePath" => "/Store", + "summary" => "Place an order for a pet", + "nickname" => "place_order", + "responseClass" => "Order", + "endpoint" => "/store/order", + "notes" => "", + "parameters" => [ + + + + + { + "name" => "body", + "description" => "order placed for purchasing the pet", + "dataType" => "", + "paramType" => "body", + } + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('GET', '/store/order/{orderId}', { + "resourcePath" => "/Store", + "summary" => "Find purchase order by ID", + "nickname" => "get_order_by_id", + "responseClass" => "Order", + "endpoint" => "/store/order/{orderId}", + "notes" => "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", + "parameters" => [ + + + { + "name" => "order_id", + "description" => "ID of pet that needs to be fetched", + "dataType" => "", + "paramType" => "path", + }, + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('DELETE', '/store/order/{orderId}', { + "resourcePath" => "/Store", + "summary" => "Delete purchase order by ID", + "nickname" => "delete_order", + "responseClass" => "void", + "endpoint" => "/store/order/{orderId}", + "notes" => "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", + "parameters" => [ + + + { + "name" => "order_id", + "description" => "ID of the order that needs to be deleted", + "dataType" => "", + "paramType" => "path", + }, + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + diff --git a/samples/server/petstore/sinatra/api/user_api.rb b/samples/server/petstore/sinatra/api/user_api.rb new file mode 100644 index 00000000000..8cbd49d72a0 --- /dev/null +++ b/samples/server/petstore/sinatra/api/user_api.rb @@ -0,0 +1,231 @@ +require 'json' + + +MyApp.add_route('POST', '/user', { + "resourcePath" => "/User", + "summary" => "Create user", + "nickname" => "create_user", + "responseClass" => "void", + "endpoint" => "/user", + "notes" => "This can only be done by the logged in user.", + "parameters" => [ + + + + + { + "name" => "body", + "description" => "Created user object", + "dataType" => "", + "paramType" => "body", + } + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('POST', '/user/createWithArray', { + "resourcePath" => "/User", + "summary" => "Creates list of users with given input array", + "nickname" => "create_users_with_array_input", + "responseClass" => "void", + "endpoint" => "/user/createWithArray", + "notes" => "", + "parameters" => [ + + + + + { + "name" => "body", + "description" => "List of user object", + "dataType" => "", + "paramType" => "body", + } + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('POST', '/user/createWithList', { + "resourcePath" => "/User", + "summary" => "Creates list of users with given input array", + "nickname" => "create_users_with_list_input", + "responseClass" => "void", + "endpoint" => "/user/createWithList", + "notes" => "", + "parameters" => [ + + + + + { + "name" => "body", + "description" => "List of user object", + "dataType" => "", + "paramType" => "body", + } + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('GET', '/user/login', { + "resourcePath" => "/User", + "summary" => "Logs user into the system", + "nickname" => "login_user", + "responseClass" => "string", + "endpoint" => "/user/login", + "notes" => "", + "parameters" => [ + + { + "name" => "username", + "description" => "The user name for login", + "dataType" => "", + "paramType" => "query", + "allowMultiple" => , + "allowableValues" => "", + + }, + + { + "name" => "password", + "description" => "The password for login in clear text", + "dataType" => "", + "paramType" => "query", + "allowMultiple" => , + "allowableValues" => "", + + }, + + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('GET', '/user/logout', { + "resourcePath" => "/User", + "summary" => "Logs out current logged in user session", + "nickname" => "logout_user", + "responseClass" => "void", + "endpoint" => "/user/logout", + "notes" => "", + "parameters" => [ + + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('GET', '/user/{username}', { + "resourcePath" => "/User", + "summary" => "Get user by user name", + "nickname" => "get_user_by_name", + "responseClass" => "User", + "endpoint" => "/user/{username}", + "notes" => "", + "parameters" => [ + + + { + "name" => "username", + "description" => "The name that needs to be fetched. Use user1 for testing. ", + "dataType" => "", + "paramType" => "path", + }, + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('PUT', '/user/{username}', { + "resourcePath" => "/User", + "summary" => "Updated user", + "nickname" => "update_user", + "responseClass" => "void", + "endpoint" => "/user/{username}", + "notes" => "This can only be done by the logged in user.", + "parameters" => [ + + + { + "name" => "username", + "description" => "name that need to be deleted", + "dataType" => "", + "paramType" => "path", + }, + + + + { + "name" => "body", + "description" => "Updated user object", + "dataType" => "", + "paramType" => "body", + } + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('DELETE', '/user/{username}', { + "resourcePath" => "/User", + "summary" => "Delete user", + "nickname" => "delete_user", + "responseClass" => "void", + "endpoint" => "/user/{username}", + "notes" => "This can only be done by the logged in user.", + "parameters" => [ + + + { + "name" => "username", + "description" => "The name that needs to be deleted", + "dataType" => "", + "paramType" => "path", + }, + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + diff --git a/samples/server/petstore/sinatra/config.rb b/samples/server/petstore/sinatra/config.rb new file mode 100644 index 00000000000..395d0587123 --- /dev/null +++ b/samples/server/petstore/sinatra/config.rb @@ -0,0 +1,2 @@ +require './my_app' +run MyApp diff --git a/samples/server/petstore/sinatra/lib/Swaggering.rb b/samples/server/petstore/sinatra/lib/Swaggering.rb new file mode 100644 index 00000000000..79aca1da2c9 --- /dev/null +++ b/samples/server/petstore/sinatra/lib/Swaggering.rb @@ -0,0 +1,154 @@ +require 'json' +require 'sinatra/base' +require 'sinatra/cross_origin' + +class Configuration + attr_accessor :base_path, :api_version, :swagger_version, :format_specifier + + def initialize + @api_version = '1.0' + @base_path = 'http://localhost:4567' + @swagger_version = '1.1' + @format_specifier = ".json" + end +end + +class Swaggering < Sinatra::Base + register Sinatra::CrossOrigin + + @@routes = {} + @@configuration = Configuration.new + + attr_accessor :configuration + + def self.configure + get("/resources" + @@configuration.format_specifier) { + cross_origin + Swaggering.to_resource_listing + } + @@configuration ||= Configuration.new + yield(@@configuration) if block_given? + end + + def self.add_route(method, path, swag={}, opts={}, &block) + fullPath = swag["resourcePath"].to_s + @@configuration.format_specifier + path + + accepted = case method + when 'get' + get(fullPath, opts, &block) + true + when 'post' + post(fullPath, opts, &block) + true + when 'delete' + delete(fullPath, opts, &block) + true + when 'put' + put(fullPath, opts, &block) + true + else + false + end + + if accepted then + resourcePath = swag["resourcePath"].to_s + ops = @@routes[resourcePath] + if ops.nil? + ops = Array.new + @@routes.merge!(resourcePath => ops) + + get(resourcePath + @@configuration.format_specifier) do + cross_origin + Swaggering.to_api(resourcePath) + end + end + + swag.merge!("httpMethod" => method.to_s.upcase) + ops.push(swag) + end + end + + def self.to_resource_listing + apis = Array.new + (@@routes.keys).each do |key| + api = { + "path" => (key + ".{format}"), + "description" => "no description" + } + apis.push api + end + + resource = { + "apiVersion" => @@configuration.api_version, + "swaggerVersion" => @@configuration.swagger_version, + "apis" => apis + } + + resource.to_json + end + + def self.to_api(resourcePath) + apis = {} + models = [] + + @@routes[resourcePath].each do |route| + endpoint = route["endpoint"].gsub(/:(\w+)(\/?)/,'{\1}\2') + path = (resourcePath + ".{format}" + endpoint) + api = apis[path] + if api.nil? + api = {"path" => path, "description" => "description", "operations" => []} + apis.merge!(path => api) + end + + parameters = route["parameters"] + + unless parameters.nil? then + parameters.each do |param| + av_string = param["allowableValues"] + unless av_string.nil? + if av_string.count('[') > 0 + pattern = /^([A-Z]*)\[(.*)\]/ + match = pattern.match av_string + case match.to_a[1] + when "LIST" + allowables = match.to_a[2].split(',') + param["allowableValues"] = { + "valueType" => "LIST", + "values" => allowables + } + when "RANGE" + allowables = match.to_a[2].split(',') + param["allowableValues"] = { + "valueType" => "RANGE", + "min" => allowables[0], + "max" => allowables[1] + } + end + end + end + end + end + + op = { + "httpMethod" => route["httpMethod"], + "description" => route["summary"], + "responseClass" => route["responseClass"], + "notes" => route["notes"], + "nickname" => route["nickname"], + "summary" => route["summary"], + "parameters" => route["parameters"] + } + api["operations"].push(op) + end + + api_listing = { + "apiVersion" => @@configuration.api_version, + "swaggerVersion" => @@configuration.swagger_version, + "basePath" => @@configuration.base_path, + "resourcePath" => resourcePath, + "apis" => apis.values, + "models" => models + } + api_listing.to_json + end +end diff --git a/samples/server/petstore/sinatra/my_app.rb b/samples/server/petstore/sinatra/my_app.rb new file mode 100644 index 00000000000..4e692eb53bc --- /dev/null +++ b/samples/server/petstore/sinatra/my_app.rb @@ -0,0 +1,9 @@ +require './lib/swaggering' + +# only need to extend if you want special configuration! +class MyApp < Swaggering + self.configure do |config| + config.api_version = '0.2' + end +end +