Giter VIP home page Giter VIP logo

sanic-dispatcher's Introduction

Sanic-Dispatcher

A Dispatcher extension for Sanic that also acts as a Sanic-to-WSGI adapter

Allows you to do this: (seriously)

from sanic import Sanic, response
from sanic_dispatcher import SanicDispatcherMiddlewareController
from flask import Flask, make_response, current_app as flask_app

app = Sanic(__name__)

dispatcher = SanicDispatcherMiddlewareController(app)

child_sanic_app = Sanic("MyChildSanicApp")

child_flask_app = Flask("MyChildFlaskApp")

@app.middleware("response")
async def modify_response(request, response):
    response.body = response.body + b"\nModified by Sanic Response middleware!"
    response.headers['Content-Length'] = len(response.body)
    return response

@app.route("/")
async def index(request):
    return response.text("Hello World from {}".format(request.app.name))

@child_sanic_app.route("/")
async def index(request):
    return response.text("Hello World from {}".format(request.app.name))

@child_flask_app.route("/")
def index():
    app = flask_app
    return make_response("Hello World from {}".format(app.import_name))

dispatcher.register_sanic_application(child_sanic_app, '/sanicchild', apply_middleware=True)
dispatcher.register_wsgi_application(child_flask_app.wsgi_app, '/flaskchild', apply_middleware=True)

if __name__ == "__main__":
    app.run(port=8001, debug=True)

Installation

pip install Sanic-Dispatcher

How To Use

First make a Sanic application the way you normally do:

from sanic import Sanic

app = Sanic(__name__) # This creates a sanic app

app becomes your 'base' or 'parent' sanic app which will accommodate the Dispatcher extension

Create a Dispatcher

from sanic_dispatcher import SanicDispatcherMiddlewareController

dispatcher = SanicDispatcherMiddlewareController(app)

dispatcher is your new dispatcher controller. Note: This takes a reference to app as its first parameter, but it does not consume app, nor does it return app.

I want to dispatch another Sanic App

app = Sanic(__name__)

dispatcher = SanicDispatcherMiddlewareController(app)

otherapp = Sanic("MyChildApp")

dispatcher.register_sanic_application(otherapp, "/childprefix")

@otherapp.route('/')
async def index(request):
    return response.text("Hello World from Child App")

Browsing to url /childprefix/ will invoke the otherapp App, and call the / route which displays "Hello World from Child App"

What if the other App is a Flask App?

from flask import Flask, make_response

app = Sanic(__name__)

dispatcher = SanicDispatcherMiddlewareController(app)
flaskapp = Flask("MyFlaskApp")

# register the wsgi_app method from the flask app into the dispatcher
dispatcher.register_wsgi_application(flaskapp.wsgi_app, "/flaskprefix")

@flaskapp.route('/')
def index():
    return make_response("Hello World from Flask App")

Browsing to url /flaskprefix/ will invoke the Flask App, and call the / route which displays "Hello World from Flask App"

What if the other App is a Django App?

import my_django_app

app = Sanic(__name__)

dispatcher = SanicDispatcherMiddlewareController(app)
# register the django wsgi application into the dispatcher
dispatcher.register_wsgi_application(my_django_app.wsgi.application,
                                     "/djangoprefix")

Browsing to url /djangoprefix/ will invoke the Django App.

Can I run a default application?

The Sanic App app you create at the start is also the default app.

When you navigate to a URL that does not match a registered dispatch prefix, this Sanic app will handle the request itself as per normal.

app = Sanic(__name__)

dispatcher = SanicDispatcherMiddlewareController(app)

otherapp = Sanic("MyChildApp")

dispatcher.register_sanic_application(otherapp, "/childprefix")

@app.route('/')
async def index(request):
    return response.text("Hello World from Default App")

@otherapp.route('/')
async def index(request):
    return response.text("Hello World from Child App")

Browsing to url / will not invoke any Dispatcher applications, so app will handle the request itself, resolving the / route which displays "Hello World from Default App"

I want to apply common middleware to the registered applications!

Easy!

import my_django_app
from flask import Flask, make_response, current_app

app = Sanic(__name__)

dispatcher = SanicDispatcherMiddlewareController(app)

child_sanic_app = Sanic("MyChildSanicApp")

child_flask_app = Flask("MyChildFlaskApp")

@app.middleware("request")
async def modify_request(request):
    request.headers['Content-Type'] = "text/plain"

@app.middleware("response")
async def modify_response(request, response):
    response.body = response.body + b"\nModified by Sanic Response middleware!"
    response.headers['Content-Length'] = len(response.body)
    return response

@app.route("/")
async def index(request):
    return response.text("Hello World from {}".format(request.app.name))

@child_sanic_app.route("/")
async def index(request):
    return response.text("Hello World from {}".format(request.app.name))

@child_flask_app.route("/")
def index():
    app = current_app
    return make_response("Hello World from {}".format(app.import_name))

dispatcher.register_sanic_application(child_sanic_app,
                                      '/childprefix', apply_middleware=True)
dispatcher.register_wsgi_application(my_django_app.wsgi.application,
                                     '/djangoprefix', apply_middleware=True)
dispatcher.register_wsgi_application(child_flask_app.wsgi_app,
                                     '/flaskprefix', apply_middleware=True)

The key here is passing apply_middleware=True to the relevant register application function. By default apply_middleware is set to False for all registered dispatcher applications.

In this example the Sanic Request Middleware modify_request will be applied to ALL requests, including those handled by applications registered on the dispatcher. The request middleware will be applied to the request before it is passed to any registered applications.

In this example the Sanic Response Middleware modify_response will be applied to ALL responses, including those which were generated by applications registered on the dispatcher. The response middleware will be applied to the response after it is processed by the registered application.

sanic-dispatcher's People

Contributors

ashleysommer avatar seemethere 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

Watchers

 avatar  avatar  avatar  avatar

sanic-dispatcher's Issues

Will this be updated to be compatible with sanic 21.3.X+?

I currently use this extension in a project and am looking at updating the sanic version to the latest one (currently 21.3.2). However this extension seems to be incompatible with the changes that the 21.3 release brought. The app seemingly starts fine, albeit with some warnings, but when I try to navigate to a page I get the following error.

[2021-03-24 18:01:25 -0500] [55771] [ERROR] Exception occurred while handling uri: 'http://0.0.0.0:1234/' Traceback (most recent call last): File "/usr/lib/python3.9/site-packages/sanic/http.py", line 125, in http1 await self.protocol.request_handler(self.request) TypeError: handle_request() missing 2 required positional arguments: 'write_callback' and 'stream_callback'
This is running the minimal code below

from sanic import Sanic
from sanic.response import json
from sanic_dispatcher import SanicDispatcherMiddlewareController
from dta.app import dispatcher_test_app

child_apps = {
    dispatcher_test_app: "/dta"
}

app = Sanic(__name__)
dispatcher = SanicDispatcherMiddlewareController(app)

def register_multiple_sanic_applications(parent_dispatcher, sanic_apps):
    for sanic_app in sanic_apps:
        parent_dispatcher.register_sanic_application(sanic_app, sanic_apps[sanic_app], apply_middleware=True)

@app.route("/")
async def hello_world(request):
    return json({"main_app": "hello world"})

register_multiple_sanic_applications(dispatcher, child_apps)

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=1234, debug=True)

The contents for dta.app from the import in the code above

from sanic import Sanic
from sanic.response import json

dispatcher_test_app = Sanic(__name__)

@dispatcher_test_app.route("/")
async def dta_index(request):
    return json({"dispatcher_test_app": "hello world"})

After some minor investigation I found that simply instantiating the dispatcher (i.e., not registering any applications afterwards), dispatcher = SanicDispatcherMiddlewareController(app), causes this behavior so I am fairly certain it is the cause of the error I am getting.

Allow websocket connections (e.g. python-socketio) on child app

Hi (it's me again... Thanks a lot for the last issue by the way !)

It seems not possible to create a websocket server, e.G. using python-socketio, on a child / dispatched app.
Is it expected behaviour ? Or am I doing it the wrong way ?

The error code happens in python-engineio but I think it comes from the dispatcher (it works fine when the socketio server is attached to the main app)

Here's the code to reproduce :

Requirements:

Sanic-Dispatcher==0.7.0.0
sanic==19.3.1
python-socketio==4.1.0

Server.py

from sanic import Sanic
from sanic.response import text
from sanic_dispatcher import SanicDispatcherMiddlewareController
import socketio

main_app = Sanic(__name__)
dispatcher = SanicDispatcherMiddlewareController(main_app)


@main_app.get('/')
def hello_main(request):
    """Route main."""
    return text('hello, main world !')


child_app = Sanic(__name__)
sio = socketio.AsyncServer(async_mode='sanic')

sio.attach(child_app)


@child_app.route('/')
async def index(request):
    return text('Hi.')


@sio.event
async def disconnect_request(sid):
    await sio.disconnect(sid)


@sio.event
async def connect(sid, environ):
    await sio.emit('my_response', {'data': 'Connected', 'count': 0}, room=sid)


@sio.event
def disconnect(sid):
    print('Client disconnected')


dispatcher.register_sanic_application(
    child_app,
    '/child'
)

if __name__ == '__main__':
    main_app.run(port=8001, debug=True)

client.py :

import socketio

sio = socketio.Client()
url = 'ws://localhost:8001/'
path = '/child/socket.io/'


@sio.event
def connect():
    print("Connected")


@sio.event
def disconnect():
    print("Disconnected")


sio.connect(url, socketio_path=path)

Error code when running server.py then connect.py :

[2019-06-19 10:55:55 +0200] [16801] [INFO] Goin' Fast @ http://127.0.0.1:8001
before_start <sanic.app.Sanic object at 0x7fcdfb998e80>
[2019-06-19 10:55:55 +0200] [16808] [INFO] Starting worker [16808]
[2019-06-19 10:55:58 +0200] - (sanic.access)[INFO][127.0.0.1:47244]: GET http://localhost:8001/socket.io/?transport=polling&EIO=3&t=1560934558.9213946  200 166
Fatal error on transport TCPTransport
protocol: <sanic.server.HttpProtocol object at 0x7fcde9927a48>
transport: <TCPTransport closed=False reading=False 0x2a50478>
Traceback (most recent call last):
  File "uvloop/handles/stream.pyx", line 827, in uvloop.loop.__uv_stream_on_read_impl
  File "/home/.../.virtualenvs/.../lib/python3.6/site-packages/sanic/server.py", line 267, in data_received
    self.parser.feed_data(data)
  File "httptools/parser/parser.pyx", line 196, in httptools.parser.parser.HttpParser.feed_data
httptools.parser.errors.HttpParserUpgrade: 328
[2019-06-19 10:55:58 +0200] [16808] [ERROR] Exception occurred while handling uri: 'ws://localhost:8001/socket.io/?transport=websocket&EIO=3&sid=4ca8ac6c0cdc43a09c9426829ae9f5be&t=1560934558.930295'
Traceback (most recent call last):
  File "/home/.../.virtualenvs/.../lib/python3.6/site-packages/sanic/app.py", line 917, in handle_request
    response = await response
  File "/usr/lib/python3.6/asyncio/coroutines.py", line 110, in __next__
    return self.gen.send(None)
  File "/home/.../.virtualenvs/.../lib/python3.6/site-packages/engineio/asyncio_server.py", line 220, in handle_request
    packets = await socket.handle_get_request(environ)
  File "/usr/lib/python3.6/asyncio/coroutines.py", line 110, in __next__
    return self.gen.send(None)
  File "/home/.../.virtualenvs/.../lib/python3.6/site-packages/engineio/asyncio_socket.py", line 89, in handle_get_request
    return await getattr(self, '_upgrade_' + transport)(environ)
  File "/usr/lib/python3.6/asyncio/coroutines.py", line 110, in __next__
    return self.gen.send(None)
  File "/home/.../.virtualenvs/.../lib/python3.6/site-packages/engineio/asyncio_socket.py", line 128, in _upgrade_websocket
    return await ws(environ)
  File "/usr/lib/python3.6/asyncio/coroutines.py", line 110, in __next__
    return self.gen.send(None)
  File "/home/.../.virtualenvs/.../lib/python3.6/site-packages/engineio/async_drivers/sanic.py", line 119, in __call__
    self._sock = await protocol.websocket_handshake(request)
AttributeError: 'HttpProtocol' object has no attribute 'websocket_handshake'
[2019-06-19 10:55:58 +0200] - (sanic.access)[INFO][127.0.0.1:47246]: GET ws://localhost:8001/socket.io/?transport=websocket&EIO=3&sid=4ca8ac6c0cdc43a09c9426829ae9f5be&t=1560934558.930295  500 144

Thanks a lot !

url_for and dispatched application

This is not really an issue but I was just wondering if you have any idea how to sort out url_for for a dispatched app. If we have something like:

app = Sanic( 'myapp' )
sub_section = Sanic( 'sub_section' )
dispatcher = SanicDispatcherMiddlewareController( app )

dispatcher.register_sanic_application( sub_section, '/subsection' )

@sub_section.route( '/' )
def hello_sub( request ):
     return text( sub_section.url_for( 'hello_sub' ) ) # this returns '/' instead of '/subsection/'

app.run()

Have you had any thoughts about this or did you have any similar situation you can share about? Maybe monkey-patching url_for and walk the tree of applications might be a viable solution?

Sanic-to-WSGI adapter Example

The project claims to be a Sanic-to-WSGI adapter, I'd love to see a trivial example of that in the documentation.

Is there a "pass-through" dispatcher that doesn't touch the routes? I simply want to use Sanic behind gunicorn or Zappa or whatever WSGI server I want, nothing more. Can I do that with this?

Module not found errors on version 0.7.0

After upgrading to this version I am getting the following errors:

Traceback (most recent call last):
  File "/usr/lib/python3.7/site-packages/sanic_dispatcher/extension.py", line 14, in <module>
    from setuptools.extern import packaging
ModuleNotFoundError: No module named 'setuptools.extern'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "app.py", line 3, in <module>
    from sanic_dispatcher import SanicDispatcherMiddlewareController
  File "/usr/lib/python3.7/site-packages/sanic_dispatcher/__init__.py", line 9, in <module>
    from .extension import SanicDispatcherMiddleware, SanicDispatcherMiddlewareController
  File "/usr/lib/python3.7/site-packages/sanic_dispatcher/extension.py", line 16, in <module>
    from pkg_resources.extern import packaging
ModuleNotFoundError: No module named 'pkg_resources.extern'

I've already re-installed setuptools (version 41.0.1), but I am thinking it is related to this perhaps:

anntzer/pypi2pkgbuild#2 (comment)

I do have the packaging library which seems to be what the script is looking for as that library contains the module version which is what is used in the script. Also, from the pkg_resources library the only relevant import I see is parse_version. So basically, what's valid on my end is:

from pkg_resources import parse_version
and
from packaging import version

EDIT

It seems there was something wrong with the package provided by my Linux distros repo. After re-installing with pip the issue seems to be gone. Sorry about that!

host based routing doesn't work

Hi Ashley,
I finally get to use your extension for one of my project (it will be a CMS that can serve websites on multiple domains with loadable modules) but I'm afraid the host based routing doesn't work. Here's an example:

from sanic import Sanic
from sanic.response import text
from sanic_dispatcher import SanicDispatcherMiddlewareController
from sanic.exceptions import NotFound

app = Sanic( 'app' )
dispatcher = SanicDispatcherMiddlewareController( app )

child_app = Sanic( 'child' )
dispatcher.register_sanic_application( child_app, '/', [ 'www.test.it' ] )

child_app2 = Sanic( 'child2' )
dispatcher.register_sanic_application( child_app2, '/', [ 'www.test.com' ] )

child_child_app2 = Sanic( 'child_child')

child_dispatcher = SanicDispatcherMiddlewareController( child_app2 )
child_dispatcher.register_sanic_application( child_child_app2, '/test' )

@child_child_app2.route( '/test' )
async def hello_child( request ):
    return text( 'hello from www.test.com/test/test')

@child_app.route( '/' )
async def hello( request ):
    return text( 'Hello from www.test.it' )

@child_app2.route( '/' )
async def hello2( request ):
    return text( 'Hello from www.test.com' )

@child_app2.route( '/test' )
async def hello_test( request ):
    return text( 'Hello from www.test.com/test' )

app.run( host = '127.0.0.1', port = 80, debug = True )

I changed my host file so that www.test.it and www.test.com alias localhost, if I try to point my browser at:

http://www.test.it
http://www.test.com
http://www.test.com/test
http://www.test.com/test/test

Sanic will always return exceptions.NotFound.

Can't dispatch a CORS-enabled Sanic application

Hi,

When using the sanic-cors package (sanic-cors==0.9.8, sanic_dispatcher==0.6.0.0, Sanic==19.3.1, python 3.6) and this piece of code:

from sanic import Sanic
from sanic.response import text
from sanic_cors import CORS
from sanic_dispatcher import SanicDispatcherMiddlewareController

main_app = Sanic(__name__)
dispatcher = SanicDispatcherMiddlewareController(main_app)


@main_app.get('/')
def hello_main(request):
    """Route main."""
    return text('hello, main world !')


child_app = Sanic(__name__+'__')
CORS(child_app)


@child_app.route("/", methods=['GET', 'OPTIONS'])
def hello_world(request):
    """Cors route."""
    return text("Hello, cross-origin-world!")


dispatcher.register_sanic_application(child_app, '/cors', apply_middleware=True)

if __name__ == '__main__':
    main_app.run(port=8001, debug=True)

When querying /cors, I get an error message :

[2019-06-17 14:52:30 +0200] - (sanic.access)[INFO][127.0.0.1:38858]: GET http://localhost:8001/favicon.ico  404 43
[2019-06-17 14:52:35 +0200] [30223] [ERROR] Exception occurred while handling uri: 'http://localhost:8001'
Traceback (most recent call last):
  File "/home/.../.virtualenvs/.../lib/python3.6/site-packages/sanic/app.py", line 885, in handle_request
    response = await self._run_request_middleware(request)
  File "/usr/lib/python3.6/asyncio/coroutines.py", line 110, in __next__
    return self.gen.send(None)
  File "/home/.../.virtualenvs/.../lib/python3.6/site-packages/spf/framework.py", line 497, in _run_request_middleware
    "App must be running before you can run middleware!"
AssertionError: App must be running before you can run middleware!
[2019-06-17 14:52:35 +0200] [30223] [DEBUG] CORS: Request to '' matches CORS resource '/*'. Using options: {'origins': ['.*'], 'methods': 'DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT', 'allow_headers': ['.*'], 'expose_headers': None, 'supports_credentials': False, 'max_age': None, 'send_wildcard': False, 'automatic_options': False, 'vary_header': True, 'resources': '/*', 'intercept_exceptions': True, 'always_send': True}
[2019-06-17 14:52:35 +0200] [30223] [DEBUG] CORS: Cannot find the request context. Is request already finished?

Any way to fix this ? I know that this package hasn't been maintained for a long time - do you have any other option to dispatch multiple sanic apps or fix this issue ?

Thanks a lot !

Gino not initalized error when using SanicDispatcherMiddlewareController

Context

Coming from Flask I thought I could initialize the DB in the child app and everything would be fine even after using dispatcher middle-ware since I've done this in Flask. For example in Flask with dispatcher middle-ware in the child app.py I'd do something like:

with app.app_context():
    db.init_app(app)
    db.create_all()

Indeed everything works if I run the child sanic app on it's own, but as soon as I use the SanicDispatcherMiddlewareController and do dispatcher.register_sanic_application(child_app, '/child_app', apply_middleware=True) I get the following error when I try to query the DB (Postgresql):

Error

Traceback (most recent call last):
  File "/usr/lib/python3.7/site-packages/sanic/app.py", line 885, in handle_request
    response = await self._run_request_middleware(request)
  File "/usr/lib/python3.7/site-packages/sanic/app.py", line 1228, in _run_request_middleware
    response = await response
  File "/usr/lib/python3.7/site-packages/gino/ext/sanic.py", line 87, in on_request
    request['connection'] = await self.acquire(lazy=True)
  File "/usr/lib/python3.7/site-packages/gino/api.py", line 481, in acquire
    return self.bind.acquire(*args, **kwargs)
  File "/usr/lib/python3.7/site-packages/gino/api.py", line 501, in __getattribute__
    raise self._exception
gino.exceptions.UninitializedError: Gino engine is not initialized.

IF, however, I initialize the db on the parent app like:

parent_app.config.DB_HOST = 'localhost'
parent_app.config.DB_PORT = '5432'
parent_app.config.DB_USER = 'some_user'
parent_app.config.DB_PASSWORD = 'some_password'
parent_app.config.DB_DATABASE = 'some_db'
parent_api_db.init_app(app)

instead of the child app then it works, but I'd like to have each child initializing different db's/models so this is not really a solution for me.

As far as I can tell from tracing the execution of the code the difference is that when I initialize the db on parent app the before_server_start listener triggers in Gino() and when I initialize the db on the child app it doesn't. That's as far as I've dug into the issue.

Fairly new to Sanic so some direction would be appreciated as I am not even sure if what I am trying to get to happen makes sense within the context of Sanic.

Proposal: Adding a DomainDispatcher

My proposal is to add a second dispatcher object called DomainDispatcher that can route requests to different apps that can be registered dynamically, something like this:

app = Sanic( 'MultiSiteApp' )
dispatcher = DomainDispatcher( app )
blog1 = Sanic( 'MyFirstBlog' )
blog2 = Sanic( 'MySecondBlog' )

dispatcher.add_app( blog1, [ 'www.blog1.com' ] )
dispatcher.add_app( blog2, [ 'www.blog2.com' ] )

if __name__ == '__main__':
  app.run( host = '0.0.0.0', port = 80 )

If you are interested, I can actually work on this and send a pull request in a few days.

request.get_args method fails when querying child app

Hey (I know, it's me again !),

it seems the sanic.request.Request objects in the child app's routes are broken : they fail when calling get_args.

Package versions :

Sanic==19.3.1
Sanic-Dispatcher==0.7.1.0

Easy code to reproduce : main.py

from sanic import Sanic
from sanic.response import text
from sanic_dispatcher import SanicDispatcherMiddlewareController

main_app = Sanic(__name__)
dispatcher = SanicDispatcherMiddlewareController(main_app)


@main_app.get('/')
def hello_main(request):
    """Route main."""
    return text('hello, main world !')


child_app = Sanic(__name__)


@child_app.route("/", methods=['GET'])
def hello_world(request):
    """Cors route."""
    return text("args : {}".format(str(request.args)))


dispatcher.register_sanic_application(child_app, '/child')

if __name__ == '__main__':
    main_app.run(port=5000, debug=True)

when calling 'http://localhost:5000/child/', the server raises a 500 :

[2019-06-24 14:16:27 +0200] [31179] [ERROR] Exception occurred while handling uri: 'http://localhost:5000/'
Traceback (most recent call last):
  File "/home/.../.virtualenvs/.../lib/python3.6/site-packages/sanic/app.py", line 915, in handle_request
    response = handler(request, *args, **kwargs)
  File "main.py", line 21, in hello_world
    return text("args : {}".format(str(request.args)))
  File "/home/.../.virtualenvs/.../lib/python3.6/site-packages/sanic/request.py", line 235, in get_args
    (keep_blank_values, strict_parsing, encoding, errors)
TypeError: 'NoneType' object is not subscriptable

Seems that Request.parsed_args is not properly set and is None..

Thanks again !

Does not work with Sanic 22.12.0

After installing and using it, it gives below error.

from sanic.websocket import WebSocketProtocol
ModuleNotFoundError: No module named 'sanic.websocket'

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.