Giter Site home page Giter Site logo

resty's Introduction

Resty

Introduction

Resty is a small, convenient interface to talk to RESTful services from Java.

Its focus is on simplicity and ease-of-use, often requiring only two lines of code to access any web service. It supports chaining several requests which is very useful in RESTful application employing HATEOAS.

Basic usage is very simple: Create a Resty instance, use authenticate methode to add credentials, then call one of the content type specific methods. The idea is that the method name will convey the expected content type you can then operate on.

import static us.monoid.web.Resty.*;

GETting an URL (as JSON):

new Resty().json(url);

POSTing to an URL (using multipart/form-data) and expecting JSON back:

new Resty().json(url, form(data("name", "Don Draper"), data("occupation", "Ad Man")));

PUTting content and expecting JSON back:

new Resty().json(url, put(content(someJSON)));

DELETE a resource via URL expecting JSON back:

new Resty().json(url, delete());

Here is an example on how to use the geonames web service. It retrieves the JSON object (see json.org for details) and gets the name of a place from the zip code:

Resty r = new Resty();
Object name = r.json("http://ws.geonames.org/postalCodeLookupJSON?postalcode=66780&country=DE").get("postalcodes[0].placeName");

See more examples below.

Features

  • GET, POST, PUT, DELETE for text, XML, JSON, binary
  • Fluent-style API to follow hyperlinks easily
  • Complex path queries for JSON (simple tests on fields with operators >,=,< and full boolean expressions (&&,||,!))
  • Support for XPath expressions
  • Authentication with login/passwd
  • Automatic Cookie management: IMPORTANT: Currently Resty will store cookies in a single instance of CookieHandler. System-wide!
  • Full support for multipart/form-data
  • GAE compatible (no cookie support though)

Changes

see CHANGES.rst

Status

Growing

  • Some HTTP verbs still missing (HEAD, OPTIONS among them)
  • No explicit HTML support yet. Use text(...).toString() and feed it a parser like Jericho
  • No oauth support yet.

Installation

Either create the JAR yourself (see target directory or grab the rest-*.jar file and add it to your CLASSPATH. Or grab it from Maven central:

<dependency>
<groupId>us.monoid.web</groupId> <artifactId>resty</artifactId> <version>0.3.2</version>

</dependency>

Compile it yourself

Use Maven 2 or 3 to build.

Examples

See http://beders.github.com/Resty/Resty/Overview.html

Getting location information from the geonames web service, published as JSON:

Resty r = new Resty();
Object name = r.json("http://ws.geonames.org/postalCodeLookupJSON?postalcode=66780&country=DE").
        get("postalcodes[0].placeName");

This gets a JSON object from the specified URL and extracts the first place name.

Getting the Google Developer calendar feed as JSON and following the first entry, which is an XML resource, extracting the title tag:

Resty r = new Resty();
String title = r.json("http://www.google.com/calendar/feeds/[email protected]/public/full?alt=json").
                xml(path("feed.entry[0].id.$t")).get("entry/title/text()", String.class);

The path(...) expression is used to extract a URL from the returned JSON object, which is then used to read an XML document.

Getting ATOM feed from Slashdot and printing article URLs:

Resty r = new Resty();
NodeList nl = r.xml("http://rss.slashdot.org/Slashdot/slashdotGamesatom").get("feed/entry/link");
for (int i = 0, len = nl.getLength(); i < len; i++) {
        System.out.println(((Element)nl.item(i)).getAttribute("href"));
}

Some supported JSON path constructs:

store.book[price>7 && price<12.999].author
store.book[!category='reference'].author

JSON Sample for paths above:

{ "store": {
   "book": [
     { "category": "reference",
       "author": "Nigel Rees",
       "title": "Sayings of the Century",
       "price": 8.95
     }, ... ]}}

Chaining calls to navigate JSON objects. This is useful if the JSON contains URIs to go down the rabbit hole so to say:

import static us.monoid.web.Resty.*;
import us.monoid.web.Resty;

JSONObject json = r.
       json("http://localhost:9999/rest/sc").
       json(path("serviceclients[displayName='Sample'].href")).
       json(path("workflows")).json(path("current")).json(path("levels[displayName='Incoming'].href")).
       json(path("ruleSets[1].EngageRouting")).object();

Developers

Contributors

Gabriel Falkenberg <[email protected]> Remi Alvergnat <[email protected]> Robert Fischer <[email protected]> https://github.com/jdmullin and othersxs

resty's People

Contributors

beders avatar benzonico avatar dominicfarr avatar gabrielf avatar jdmullin avatar matthewmichihara avatar mcohen01 avatar peet avatar toilal avatar wilfriedvanasten 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

resty's Issues

Resty source compilation error - getAcceptedTypes()

getAcceptedTypes() in us.monoid.web.XMLResource cannot override getAcceptedTypes() in us.monoid.web.AbstractResource; attempting to assign weaker access privileges; was protected

Match the function signature.

protected String getAcceptedTypes()

Wishlist: be able to ignore SSL errors

Many sites under development use https for their API but do not install a proper certificate. It would be great to be able to ignore SSL errors in Resty by calling a method on the Resty instance.

Problem checking if given string is equal to a JSONObject's property

I'm trying to loop over a json array to check if a given string is equal to the current JSONObject's property.

Here's the result from the GET /accounts request:

[
  {
    "username": "admin",
    "password": "password"
  },
  {
    "username": "a2ko",
    "password": "MABUHAY"
  },
  {
    "username": "bitoy",
    "password": "maytuko"
  }
]

Here's the method I'm having a problem with:

private void login(String username) {
  JSONArray accounts = null;
  boolean found = false;
    try {
      accounts = r.json(apiUrl + "/accounts").array();
    } catch (IOException | JSONException e) {
      e.printStackTrace();
    }

    for (int i = 0; i < accounts.length(); i++) {
      try {
        if (accounts.getJSONObject(i).getString("username") == username) {
          found = true;
          break;
        }
      } catch (JSONException e) {
      e.printStackTrace();
    }
  }
  System.out.println(found); // check if user was found
}

I can guarantee that the username parameter is not null.

JavaCC dependency has class in root package - causes OSGI build failure.

Resty currently has a dependency on javacc-4.1.jar which has classes in the root package. This causes a problem when used in an OSGI context where the construction of the manifest complains that: "The default package '.' is not permitted by the Import-Package syntax."

I checked the latest javacc-6.1.2.jar and it has the same issue, so no quick fix there I'm afraid.

Small correction

Just a small correction to be made - HATEOS should in fact be HATEOAS.

Add better support for JSON queries

Add support for full JSON expression on left hand side of predicates.
I.e. you can now write path expressions like these:

store.book[reviewed-by.name = 'JB']

where the selector in the array is a full nested path expression.

scala issue

object is a reserved word, so the following is not possible:

JSONResource.object ()

.toObject() would be fine

Allow setting a base url

It would be awesome if you could create Resty with a base url.

Resty r = new Resty("http://localhost/myApi");
r.json("/users")

Allow multipart PUT

Haven't looked too much into this, but it looks like you can POST multipart form data, but not PUT it.

Can we just change the Replacement class to accept AbstractContent instead of Content and the put method in Resty to accept AbstractContent instead of Content?

Proxy with authentication

Is it possible to specify a username and password to use with the Proxy option along with the host and port?

I can only find a host and port solution like so:
Resty rest = new Resty(Resty.Option.proxy("myproxy.com", 80));

But I can't find a way to set an authenticated proxy.

Thank you.

Exception when running in Google AppEngine

GAE doesn't support all the standard java.net classes, specifically CookieHandler & CookieManager (the complete whitelist is here: http://code.google.com/appengine/docs/java/jrewhitelist.html)

I think if you just trap the exception & ignore it, it will be fine.

java.lang.NoClassDefFoundError: java.net.CookieManager is a restricted class. Please see the Google  App Engine developer's guide for more details.
    at com.google.appengine.tools.development.agent.runtime.Runtime.reject(Runtime.java:51)
    at us.monoid.web.Resty.<clinit>(Resty.java:64)
    at org.apache.jsp.support.links_005fhtml_jsp._jspService(links_005fhtml_jsp.java:80)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:377)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260)
    at com.google.appengine.tools.development.PrivilegedJspServlet.access$101(PrivilegedJspServlet.java:23)
    at com.google.appengine.tools.development.PrivilegedJspServlet$2.run(PrivilegedJspServlet.java:59)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.google.appengine.tools.development.PrivilegedJspServlet.service(PrivilegedJspServlet.java:57)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
    at com.google.appengine.tools.development.BackendServersFilter.doFilter(BackendServersFilter.java:97)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
    at com.google.apphosting.utils.jetty.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:70)
    at org.mortbay.jetty.servlet.Dispatcher.forward(Dispatcher.java:327)
    at org.mortbay.jetty.servlet.Dispatcher.forward(Dispatcher.java:126)
    at org.tuckey.web.filters.urlrewrite.NormalRewrittenUrl.doRewrite(NormalRewrittenUrl.java:213)
    at org.tuckey.web.filters.urlrewrite.RuleChain.handleRewrite(RuleChain.java:171)
    at org.tuckey.web.filters.urlrewrite.RuleChain.doRules(RuleChain.java:145)
    at org.tuckey.web.filters.urlrewrite.UrlRewriter.processRequest(UrlRewriter.java:92)
    at org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:381)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:35)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:58)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:122)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.tools.development.BackendServersFilter.doFilter(BackendServersFilter.java:97)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
    at com.google.apphosting.utils.jetty.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:70)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:351)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at org.mortbay.jetty.Server.handle(Server.java:326)
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
    at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923)
    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:547)
    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
    at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)

Exceptions for standard http code responses

I find the use of Exceptions incorrect.

For example,

JSONResource jsonResource = resty.json(url);

If I make a call to an api using the above code and the remote service returns http 404, Resty throws an IOException. This isn't what I expect. It should return to me a JSONResource with a response code 404.

int statusCode = jsonResource.http().getResponseCode();

// statusCode == 404 

404 isn't an exceptional case, it is a standard, expected response from an http call.

Throwing an exception, especially a checked exception, is wrong. Clients need to react differently to 2xx, 3xx, 4xx, and 5xx type response, wrapping every non 2xx http in a checked exception hides important information.

POST

Trying to do a post here on Android. Stuck on the multipart/form data.

new Resty().json(url, form(data("name", "Draper"),
data("occupation", "Ad Man")));

Not quite understanding the example. The second param is expecting an AbstractContent, but I have no idea how to create one. Tried BasicNameValuePair, which didn't work.

Unable to override Accept header

Resty won't let me override Accept, it only lets me add stuff to it. My Rails app is serving a Resty.text() request with HTML because Resty places text/html before text/plain in its Accept. Neither dontSend nor alwaysSend allow me ot override this behavior.

Ability to read content after catching exception

As you may know, some RESTful servers provide additional information about an error in the http content, but with today's Resty implementation one simpy gets an IOException if there is a 500 server error. Now it's impossible to dig further as the IOException carries no further information :-(

I've made a tiny and fully compatible adjustment to a subclass of Resty to handle this. I let Resty catch IOExeptions, and re-throw RestyExceptions instead. These RestyExceptions are simply subclasses of IOExceptions that embeds an AbstractResource. Problem solved :-)

I'd be happy to provide you my implementation. As I said, it's a tiny and fully compatible adjustment. It does not require any changes to existing users of your library. It just makes it better. My implementation also allows a user to add additional http request parameters which is required by some servers.

Just email me at [email protected] and I'll contribute my code!

System.out.println("GOT:" + json);

I'm reading large sets of JSON data and this row in the class JSONPathQuery.java seriously decreases the speed of reading.

Can this row be removed in an upcoming edition?

IMHO: System.out.println shouldn't be used at all in code like this. Considered Log4J?

Resty broken on Java 1.5

Resty breaks when running on Java 1.5. I looked at the code for Resty.java and can see that's intended to work, but it's not enough. This is the failing code:

    try {
            java.net.CookieHandler.setDefault(new java.net.CookieManager());
    } catch (Throwable oops) {
        System.err.println("No CookieHandler. Running on GAE? Fine. No cookie support for you!");
    }

On Java 1.5, the loading of the Resty class itself, where this static code is located is breaking, so it never reaches the try-catch part. The solution is to simply put this code in a separate "CookieFix" class and instantiate such a class from the static context of the Resty class. Now you can wrap that instantiation in the try-catch loop and it will work.

JSONParser(InputStream) not recognised

Am I missing a library?

Line 35 of us.monoid.web.JSONResource

List<?> ary = new JSONParser(inputStream).parseArray();

But I dont have JSONParser on the classpath. Im using this in an Android app, if this makes any difference?

Json Delete

I am using Resty 0.3.2 on android
I am calling delete like this :
request.json("http://example.com:port/customer/4", delete());

here is the error , is my falut or Resty ?

02-26 00:10:56.736: W/System.err(1116): java.io.IOException: BufferedInputStream is closed
02-26 00:10:56.747: W/System.err(1116): at java.io.BufferedInputStream.streamClosed(BufferedInputStream.java:118)
02-26 00:10:56.747: W/System.err(1116): at java.io.BufferedInputStream.read(BufferedInputStream.java:279)
02-26 00:10:56.747: W/System.err(1116): at java.io.InputStream.read(InputStream.java:163)
02-26 00:10:56.747: W/System.err(1116): at us.monoid.web.AbstractResource.fill(AbstractResource.java:44)
02-26 00:10:56.757: W/System.err(1116): at us.monoid.web.Resty.fillResourceFromURL(Resty.java:432)
02-26 00:10:56.757: W/System.err(1116): at us.monoid.web.Resty.doPOSTOrPUT(Resty.java:394)
02-26 00:10:56.757: W/System.err(1116): at us.monoid.web.Resty.json(Resty.java:223)
02-26 00:10:56.757: W/System.err(1116): at us.monoid.web.Resty.json(Resty.java:228)
02-26 00:10:56.757: W/System.err(1116): at com.example.resttest.RestTasks.doRequest(RestTasks.java:57)
02-26 00:10:56.757: W/System.err(1116): at com.example.resttest.RestTasks.doInBackground(RestTasks.java:29)
02-26 00:10:56.757: W/System.err(1116): at com.example.resttest.RestTasks.doInBackground(RestTasks.java:1)
02-26 00:10:56.767: W/System.err(1116): at android.os.AsyncTask$2.call(AsyncTask.java:287)

02-26 00:10:56.767: W/System.err(1116): at java.util.concurrent.FutureTask.run(FutureTask.java:234)
02-26 00:10:56.767: W/System.err(1116): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
02-26 00:10:56.777: W/System.err(1116): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
02-26 00:10:56.777: W/System.err(1116): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
02-26 00:10:56.793: W/System.err(1116): at java.lang.Thread.run(Thread.java:856)

EDIT:
I am using all the others methods successful only the delete is creating this error

Documentation completely incorrect

Hi there,
I've been trying to use your library and the docs are, to be generous, not quite up to date.

There is no default empty constructor for Resty itself. And it's not possible to just pass in the default Option classes.

Please update with correct usage.

Thank you!

Propagate exceptions

Overall a nice little library but needs to be ridden of those ugly e.printStackTrace() calls.
Please, let the exceptions propagate and/or wrap in your own Exception class.

The api catches exceptions and print them to System.out, which renders it unusable to me.

connection timeout

Funny bug that i've discovered, when mistakenly set timeout to 10 milliseconds

the bug in this code

void fill(URLConnection anUrlConnection) throws IOException {
urlConnection = anUrlConnection;
try {
inputStream = anUrlConnection.getInputStream();
} catch (IOException e) {
// Per http://docs.oracle.com/javase/1.5.0/docs/guide/net/http-keepalive.html
// (comparable documentation exists for later java versions)
// if an HttpURLConnection was used clear the errorStream and close it
// so that keep alive can keep doing its work
if (anUrlConnection instanceof HttpURLConnection) {
HttpURLConnection conn = (HttpURLConnection) anUrlConnection;
InputStream es = new BufferedInputStream(conn.getErrorStream());

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            // read the response body
            byte[] buf = new byte[1024];
            int read = -1;
            while ((read = es.read(buf)) > 0) {
                baos.write(buf, 0, read);
            }

            // close the errorstream
            es.close();

            throw new IOException("Error while reading from " + conn.getRequestMethod() + ": [" + conn.getResponseCode() + "] "
                    + conn.getResponseMessage() + "\n" + new String(baos.toByteArray(), "UTF-8"), e);
        } else {
            throw e;
        }
    }
}

we are trying to read output while stream is already closed by urlConnections so never reaching throw section

Cookie usage examples?

I know it's not quite RESTful to use cookies at times like for session state persistence, but is there support for reading and writing cookies with this library? If so, can you provide examples? I can't quite deduce how to use cookies just briefly browsing over the API doc.

By the way, I had intended to use Resty for both REST API calls as well as non-REST HTTP calls (whcih thus require session cookies for some calls). The library seems really handy even for non-REST HTTP calls (over using Apache HTTPClient).

Resty post request issue

I am trying to use Resty to do a "POST". The problem is Eclipse shows an error and suggests creating a "data(String,String)" function in the sample code:

new Resty().json(url2, form(data("name", "Draper"), data("occupation", "Ad Man")));

How do I fix/avoid this?

headers and parameters

how do we add new headers and parameters to this resty while making request

not all requests will be simple urls. they will contain headers and parameters as well in real life .
so can you make the resty to accept the headers and parameters in the requests.

consider adding OSGi metadata

Hi - Resty looks great. Please consider adding OSGi metadata to the Jar manifest so that Resty can be used in an OSGi environment without modification. The best way to add this would be as part of a build script or tool, which could guarantee that the metadata was kept up to date, but you can also just add it directly to a MANIFEST.MF file manually. An example would be to add these lines to your normal manifest:

Bundle-ManifestVersion: 2
Bundle-Name: Resty
Bundle-Description: A simple HTTP REST client for Java
Bundle-SymbolicName: us.monoid.resty
Bundle-Vendor: Robert Fischer
Bundle-Version: 0.3.1
Export-Package:
us.monoid.json,
us.monoid.util,
us.monoid.web,
us.monoid.web.auth,
us.monoid.web.mime

Problem with the maven repository

I can't get this to work for some reason.

i defined the repository like so:

 
 "<repositories>
    <repository>
        <id>resty</id>
        <url>http://repo.smokejumperit.com</url>
    </repository>
</repositories>"

and then the dependency:

<dependency>       
       <groupId>RobertFischer</groupId>
      <artifactId>resty</artifactId>
      <version>0.3.1.3</version>
    </dependency>

But no maven dependencies gets updated.>

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.