Code Monkey home page Code Monkey logo

duckrails's Introduction

DuckRails GitHub version Build Status

DuckRails is a development tool.

Its main purpose is to allow developers to quickly mock API endpoints that for many possible reasons they can't reach at a specific time.

If it looks like a duck, walks like a duck and quacks like a duck, then it's a duck 🦆

Home Page

How it works

The application allows creating new routes dynamically to which developers can assign static or dynamic responses:

  • body
  • headers
  • content type
  • status code

or even cause delays, timeouts etc.

Guides

The repository's wiki pages contain all you need to know.

You can find the old DuckRails' guides at my blog.

Example

Mocks index page

Mocks index page

Changing mocks order

Change mocks order

Setting general mock properties

General mock properties

Defining the response body

Defining the response body

Setting response headers

Setting response headers

Setting some advanced configuration (delays, dynamic headers, content type & status)

Advanced configuration

Upon save the route becomes available to the application and you can use the endpoint:

Request Headers

Supported response functionality

You can define static or dynamic responses for a mock.

Currently supported dynamic types are:

  • Embedded Ruby
  • JavaScript

Embedded Ruby

When specifying dynamic content of embedded Ruby (more options to be added), you can read as local variables:

  • @parameters: The parameters of the request
  • @request: The request
  • @response: The response

JavaScript

When specifying dynamic content of JavaScript type, you can read as local variables:

  • parameters: The parameters of the request
  • headers: The request headers

The script should always return a string (for JSON use JSON.stringify(your_variable))

Route paths

You can specify routes and access their parts in the @parameters variable, for example:

/authors/:author_id/posts/:post_id

give you access to the parameters with:

@parameters[:author_id]

@parameters[:post_id]

Quick setup (development environment)

  • Clone the repository.
  • Copy the sample database configuration file (config/database.yml.sample) under config/database.yml and edit it to reflect your preferred db configuration (defaults to sqlite3). If you change the database adapter, make sure you include the appropriate gem in your Gemfile (ex. for mysql gem 'mysql2')
  • Execute bundle install to install the required gems.
  • Execute rake db:setup to setup the database.
  • Execute rails server to start the application on the default port.
  • Duckrails can be run concurrently and in parallelism, thus instead of the default rails server, you may start the puma server with something like: bundle exec puma -t 8:16 -w 3

Better setup (production environment)

  • Clone the repository.
  • Copy the sample database configuration file (config/database.yml.sample) under config/database.yml and edit it to reflect your preferred db configuration (defaults to sqlite3). If you change the database adapter, make sure you include the appropriate gem in your Gemfile (ex. for mysql gem 'mysql2')
  • Execute bundle install to install the required gems.
  • Export an env variable for your secret key base: export SECRET_KEY_BASE="your_secret_key_base_here"
  • Execute RAILS_ENV=production rake db:setup to setup the database.
  • Execute RAILS_ENV=production rake assets:precompile to generate the assets.
  • Execute bundle exec rails s -e production to start the application on the default port.
  • Duckrails can be run concurrently and in parallelism, thus instead of the default rails server, you may start the puma server with something like: RAILS_ENV=production bundle exec puma -t 8:16 -w 3

Database configuration

The application is by default configured to use sqlite3. If you want to use another configuration, update the config/database.yml accordingly to match your setup.

Docker

A docker image is available at docker hub under iridakos/duckrails.

To obtain the image use:

docker pull iridakos/duckrails

To start the application and bind it to a port (ex. 4000) use:

docker run -p 4000:80 iridakos/duckrails:latest

Contributing

  1. Fork it ( https://github.com/iridakos/duckrails/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

License

This application is open source under the MIT License terms.

duckrails's People

Contributors

cedev avatar chocolateboy avatar dependabot[bot] avatar iridakos avatar jindrichskupa avatar olleolleolle avatar ouranos avatar tlatsas avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

duckrails's Issues

How to use query parameters?

Is there currently a way to use optional query parameters for an endpoint?

For example, I would like to be able to use

localhost/v1/route?optional=1&dynamic=1

and still be able to hit localhost/v1/route without the query parameters...

When I attempt to add a query parameter to a mock endpoint then it is automatically "required", or else the endpoint is no longer found when trying to hit it.

Getting request header dynamically using Javascript

Hello,

I'm trying to retrieve a value from a request header for using at body content section for my response. The request header the client sends looks like it:
Authorization: 123#abc

Then, at body content section at DuckRails, I tried to read that value this way:
var header = headers['Authorization'].split('#')[1];

But when I test the response I get a 200 Ok, but with this error:

Duckrails-Error: TypeError: Cannot read property 'split' of undefined

Am I reading the headers in a wrong way?

Create mock with return alternative

How to configure fot accept parameter empty? My ideia is return default value in case
I need create a mock example: /user/v1/user-credential
with params:
document = 123
with return:

{
   "document" : "123"
}

But, i need create same mock name /user/v1/user-credential with return alternative, example:
with params
document = 092
with return

{
   "document" : "092",
   "name" : "Renato"
}

How to make this? I look the documentation, but not found solution.

SQLite3::SQLException

Puma caught this error: SQLite3::SQLException: no such table: application_state: SELECT  "application_state".* FROM "application_state"  ORDER BY "application_state"."id" DESC LIMIT 1 (ActiveRecord::StatementInvalid)
/var/lib/gems/2.5.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:91:in `initialize'
/var/lib/gems/2.5.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:91:in `new'
/var/lib/gems/2.5.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:91:in `prepare'
/var/lib/gems/2.5.0/gems/activerecord-4.2.11.1/lib/active_record/connection_adapters/sqlite3_adapter.rb:284:in `block in exec_query'
/var/lib/gems/2.5.0/gems/activerecord-4.2.11.1/lib/active_record/connection_adapters/abstract_adapter.rb:484:in `block in log'
/var/lib/gems/2.5.0/gems/activesupport-4.2.11.1/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
/var/lib/gems/2.5.0/gems/activerecord-4.2.11.1/lib/active_record/connection_adapters/abstract_adapter.rb:478:in `log'
/var/lib/gems/2.5.0/gems/activerecord-4.2.11.1/lib/active_record/connection_adapters/sqlite3_adapter.rb:281:in `exec_query'
/var/lib/gems/2.5.0/gems/activerecord-4.2.11.1/lib/active_record/connection_adapters/abstract/database_statements.rb:356:in `select'
/var/lib/gems/2.5.0/gems/activerecord-4.2.11.1/lib/active_record/connection_adapters/abstract/database_statements.rb:32:in `select_all'
/var/lib/gems/2.5.0/gems/activerecord-4.2.11.1/lib/active_record/connection_adapters/abstract/query_cache.rb:70:in `select_all'
/var/lib/gems/2.5.0/gems/activerecord-4.2.11.1/lib/active_record/querying.rb:39:in `find_by_sql'
/var/lib/gems/2.5.0/gems/activerecord-4.2.11.1/lib/active_record/relation.rb:639:in `exec_queries'
/var/lib/gems/2.5.0/gems/activerecord-4.2.11.1/lib/active_record/relation.rb:515:in `load'
/var/lib/gems/2.5.0/gems/activerecord-4.2.11.1/lib/active_record/relation.rb:243:in `to_a'
/var/lib/gems/2.5.0/gems/activerecord-4.2.11.1/lib/active_record/relation/finder_methods.rb:500:in `find_nth_with_limit'
/var/lib/gems/2.5.0/gems/activerecord-4.2.11.1/lib/active_record/relation/finder_methods.rb:484:in `find_nth'
/var/lib/gems/2.5.0/gems/activerecord-4.2.11.1/lib/active_record/relation/finder_methods.rb:127:in `first'
/var/lib/gems/2.5.0/gems/activerecord-4.2.11.1/lib/active_record/querying.rb:3:in `first'
/home/watcher/duckrails/app/models/duckrails/application_state.rb:24:in `instance'
/home/watcher/duckrails/lib/duckrails/synchronizer.rb:10:in `call'
/var/lib/gems/2.5.0/gems/railties-4.2.11.1/lib/rails/rack/logger.rb:38:in `call_app'
/var/lib/gems/2.5.0/gems/railties-4.2.11.1/lib/rails/rack/logger.rb:20:in `block in call'
/var/lib/gems/2.5.0/gems/activesupport-4.2.11.1/lib/active_support/tagged_logging.rb:68:in `block in tagged'
/var/lib/gems/2.5.0/gems/activesupport-4.2.11.1/lib/active_support/tagged_logging.rb:26:in `tagged'
/var/lib/gems/2.5.0/gems/activesupport-4.2.11.1/lib/active_support/tagged_logging.rb:68:in `tagged'
/var/lib/gems/2.5.0/gems/railties-4.2.11.1/lib/rails/rack/logger.rb:20:in `call'
/var/lib/gems/2.5.0/gems/sprockets-rails-3.2.1/lib/sprockets/rails/quiet_assets.rb:13:in `call'
/var/lib/gems/2.5.0/gems/actionpack-4.2.11.1/lib/action_dispatch/middleware/request_id.rb:21:in `call'
/var/lib/gems/2.5.0/gems/rack-1.6.11/lib/rack/methodoverride.rb:22:in `call'
/var/lib/gems/2.5.0/gems/rack-1.6.11/lib/rack/runtime.rb:18:in `call'
/var/lib/gems/2.5.0/gems/activesupport-4.2.11.1/lib/active_support/cache/strategy/local_cache_middleware.rb:28:in `call'
/var/lib/gems/2.5.0/gems/rack-1.6.11/lib/rack/lock.rb:17:in `call'
/var/lib/gems/2.5.0/gems/actionpack-4.2.11.1/lib/action_dispatch/middleware/static.rb:120:in `call'
/var/lib/gems/2.5.0/gems/rack-1.6.11/lib/rack/sendfile.rb:113:in `call'
/var/lib/gems/2.5.0/gems/railties-4.2.11.1/lib/rails/engine.rb:518:in `call'
/var/lib/gems/2.5.0/gems/railties-4.2.11.1/lib/rails/application.rb:165:in `call'
/var/lib/gems/2.5.0/gems/rack-1.6.11/lib/rack/content_length.rb:15:in `call'
/var/lib/gems/2.5.0/gems/puma-3.12.0/lib/puma/configuration.rb:225:in `call'
/var/lib/gems/2.5.0/gems/puma-3.12.0/lib/puma/server.rb:658:in `handle_request'
/var/lib/gems/2.5.0/gems/puma-3.12.0/lib/puma/server.rb:472:in `process_client'
/var/lib/gems/2.5.0/gems/puma-3.12.0/lib/puma/server.rb:332:in `block in run'
/var/lib/gems/2.5.0/gems/puma-3.12.0/lib/puma/thread_pool.rb:133:in `block in spawn_thread'

headless Debian10 x64

Request HTTP in ResponseBody

Is possible run request http with javascript into responseBody the of mock? I need to import other lib for decrypt content responseBody.

Route Synchronizer is not multi-worker-safe

The route Synchronizer is not threadsafe and fails to consistently reload routes across threads.

Test case:

  1. Run puma with many threads and a single worker (or low count): puma -t 16:16 -w 0
  2. Add 2 basic mocks. Mock A and Mock B
  3. Run apache bench against Mock A: ab -c 20 -n 200000 http://URL-FOR-MOCK-A
  4. Toggle Mock B on and off a few times.

Expected:
Routes reload as expected.

Observed:
Routes do not load consistently across some app threads and app throws errors due to missing routes.

(PR brewing)

pass JSON values from request to response

Hello,
this is my first work with any mock server.
I am sending from client(via method POST) to duckrails json data.
Is possible pass the values from the clients request into response a return them back to the client?

Thank You

How better computer definition to run duckrails

I'm using an AWS instance of medium type (4gb ram and 2 vcpu), but when the mock is accessed by some cell phones, it is inoperative and sometimes after a few minutes it returns. Anybody can say me tell me something related to this? What is the ideal machine? Is there a different configuration to use?

Layout missing

After bundle install and rake db:setup, when I run my rails server, the layout is broken (missing). I get errors such as this one:

Started GET "/javascripts/vendor/modernizr.js" for ::1 at 2016-03-19 08:41:12 +0100

ActionController::RoutingError ((╯°□°)╯︵ ┻━┻ : No route matches [GET] "/javascripts/vendor/modernizr.js"):

Tool looks really useful and looking forward to use it!

Allow user to save response bodoy

Hi,

When developing, I'm using Duckrails to mock my API. Sometimes I'd like the same endpoint to respond with a different body (and/or a different status code).

Do you think this could make sense to add this feature?

It can wether be with a "special" query (e.g. ?duckrails_body_name=no_user) or on the web interface?

I'm happy to provide a PR if you are happy with this.

How to require javascript file?

i want to require some *.js file, how can i do.

i've try require('*.js'), but return empty page. i think there is some error with require method

Allow users to move mock under a scope

If I've a lot of mock, it might be nice to be able to prepend the route of all my mocks by something (e.g add /api/v1 to some mock).

I'd love to have a view with all my mocks and drag them to build my desired path.
It might also be interesting to use this feature to create a "common" configuration (e.g. common headers)

If you'd like this feature, I'm happy to propose an implementation.

Cheers :)

Multi-threading

Whenever you do a sleep or proxy data from another service, all mocks and the UI wait for the current operation to finish.

Overwriting headers in Advanced causes 500

DuckRails 2.1.9
Running on Docker

I was just playing around, and wanted to dynamically change responses headers. When I tried returning a JSON object with a headers key I get a 500: "We're sorry, but something went wrong".

To validate that I was writing the JS correctly, I just grabbed your example code for the response body, added the headers key and returned it.

Here is the code

var date = new Date();
date.setDate(date.getDate() -  Math.floor(Math.random() * 30 + 1) );

var obj = {
 "headers":{
       "current_page": Math.floor((Math.random() * 456) + 1),
        "started_reading": date.toDateString()
   }
}

return JSON.stringify(obj);

Expected: Headers would now have a current_page and started_reading key in my curl.

Actual: Return code 500, HTML with

<div class="dialog">
    <div>
      <h1>We're sorry, but something went wrong.</h1>
    </div>
    <p>If you are the application owner check the logs for more information.</p>
  </div>

Provide headers as a hash in the Javascript context

When evaluating Javascript code, provide the headers as a hash.

At the moment the headers are provided as array of two-element arrays making it hard to be accessed in the script.

Current state

[["Content-Type", "text/html"], ["header-name", "header-value"]]

Desired state

{
  "Content-Type": "text/html",
  "header-name": "header-value"
}

Overwrite status code return

How to change status code in return? I have 3 mock and need only one, more with status code different.

Im Try:

var ob = {"status_code": 500};
JSON.stringify(ob);

In Ruby ok:

<%=
{status_code: 500}.to_json
%>

No route matches

Hi, I am following the github example. After creating a new mock and save the route, when I go to /posts on cloud9 or http://localhost:3000/posts on my local machine I get this error: No route matches [GET] "/posts". Is there something I am missing?

Docker absolute volume path and runtime error

docker run --name=example_iridakos.duckrails.release-v2.1.5 -v=/Users/krystian.panek/Projects/gradle-aem-multi/duckrails:/opt/duckrails/db -p=8080:80 --rm iridakos/duckrails:release-v2.1.5
WARNING: Environment variable SECRET_KEY_BASE has not been set - Setting a random SECRET_KEY_BASE
rake aborted!
ActiveRecord::StatementInvalid: Could not find table 'mocks'
/opt/duckrails/vendor/bundle/ruby/2.4.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/sqlite3_adapter.rb:501:in `table_structure'
/opt/duckrails/vendor/bundle/ruby/2.4.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/sqlite3_adapter.rb:375:in `columns'
/opt/duckrails/vendor/bundle/ruby/2.4.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/schema_cache.rb:43:in `columns'
/opt/duckrails/vendor/bundle/ruby/2.4.0/gems/activerecord-4.2.8/lib/active_record/attributes.rb:93:in `columns'
/opt/duckrails/vendor/bundle/ruby/2.4.0/gems/activerecord-4.2.8/lib/active_record/attributes.rb:98:in `columns_hash'
/opt/duckrails/vendor/bundle/ruby/2.4.0/gems/activerecord-4.2.8/lib/active_record/relation/delegation.rb:48:in `columns_hash'

but when I use just duckrails on the left side of volume it works.

docker run --name=example_iridakos.duckrails.release-v2.1.5 -v=duckrails:/opt/duckrails/db -p=8080:80 --rm iridakos/duckrails:release-v2.1.5

still when using absolute path or relative path, in both cases seems that volume is working / file duckrails/production.sqlite3 is created... so that seems that is is something wrong later on DuckRails runtime side.

this is blocking me in case of using Duckrails on Windows on which I need to support Docker Toolbox in which absolute volume paths usage is essential.

it would be nice to have it fixed :)

greetings, Krystian

possible styling issues

i've setup the application and so far it seems to be working, however the styling is definitely off. parts of the page, particularly the header and footer look like the css is mostly missing. my first guess is that it has to do with differences in the foundation-rails gem. what gem version works for you guys?

Provide a mock show page

Provide a mock show page that will allow users to view a mock configuration with a legit layout.

  • Use code formatting for body content & script
  • Description links should be rendered as link, not as text

View request body

Hi guys,

I'm wondering, if there is any way to log body of incomming requests?

Thank you in advance.

Dupplicating a mock

Hello,

I often dupplicate manually many endpoints containing long headers. Which takes very long to copy past to a new one.

It would be great to have a button in a "mock", allowing to "dupplicate a mock".
A modal would show asking which name we want to save the mock as.

Thanks !

Pagination resets after activating a mock

If I'm on the second page of results (e.g. mocks?page=10) and I click the to activate a mock, I am redirect without the page parameter thereby losing what page I'm on.

Support python script as body type

It would be nice to have something like python script as available body type.

Response body

I was thinking of creating a template python script which would read from the stdin and then execute(evaluate?) the input.

Then, via ruby, we could start a process (using the childprocess gem) like python lib/python/template.py and send the mock's body to the process' stdin.

  • Is it possible to execute a python script isolated (in a safe context)?
  • How could we get the evaluated script's output?

Validation parameter in advanced mode

Is possible verification in advanced mode:

Not work for me:

var status_code =500;
if (parameters['idOrigem'] == 64){
    var status_code = 200;
    return JSON.stringify(status_code);
} else if (parameters['idOrigem'] == "164") {
   var status_code = 400;
   return JSON.stringify(status_code);
} else {
return JSON.stringify(status_code);
}

Validating incoming data

Hi, this is a cool tool, but a little outside what I was hoping to use it for.

I'm building an XML API which is going to spend most of it's time receiving data rather than serving it - as such, the most important bit is the format in which the data is received - that is, does it match what I'll be expecting?

If something which allows for this type of validation could be added, that would make my life much easier.

Thank you.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.