Git Product home page Git Product logo

json-api's People

Contributors

gregpeden avatar lindyhopchris 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

Watchers

 avatar  avatar  avatar  avatar

json-api's Issues

How to add custom action to resource constroller?

Hi! I found nothing in the documentation about my question. How I can add custom action to resource controller? For instance: I have PostController, this controller extends JsonApiController, inherits index, create, update, etc. And I want to add 'share' action.

Working with collections

Hi,
I created a client which is receiving a response similar to this:

 {
    "data": [
        {
            "type": "ENTITY",
            "id": "identifier",
            "attributes": {
                "name": "My name 1",
                "number": 1,
            },
            "relationships": {
                "relation": {
                    "data": {
                        "type": "type",
                        "id": "identifier2"
                    }
                },
            },
            "links": {
                "self": "link1"
            }
        },
        {
            "type": "ENTITY",
            "id": "identifier2",
            "attributes": {
                "name": "My name 2",
                "number": 2,
            },
            "relationships": {
                "relation": {
                    "data": {
                        "type": "type",
                        "id": "identifier2"
                    }
                },
            },
            "links": {
                "self": "link1"
            }
        },
        {
            "type": "ENTITY",
            "id": "identifier",
            "attributes": {
                "name": "My name 3",
                "number": 3,
            },
            "relationships": {
                "relation": {
                    "data": {
                        "type": "type",
                        "id": "identifier3"
                    }
                },
            },
            "links": {
                "self": "link1"
            }
        },        
    ]
}

As you can see, inside data I receive an array of Entities, I don't know how I can iterate in this entities I receive in the array.
It would be great to have an example on how to do that!

Thanks in advance,
Julio

CloudCreativity\JsonApi\Error\ErrorObject toArray() enhancement?

Could it be possible to have the toArray() method (in CloudCreativity\JsonApi\Error\ErrorObject line 332) return only not null values?

I'll try to explain my scenario. I wanna be able to use this class to build application logic errors (as opposed to an Exception which handles "exceptional" situations) that I can then use to respond a client with using the following syntax:

$error = new ErrorObject([
    'status' => '418',
    'code' => '1',
    'title' => "I'm an error object",
    'detail' => 'error object',
    'meta' => ['render' => 'form'],
]);

return $this->reply()->respond('418', ['errors' => [$error->toArray()]]);

Currently if I do it like that, I get the following response:

{
  "errors": [
    {
      "id": null,
      "links": null,
      "status": "418",
      "code": "1",
      "title": "I'm an error object",
      "detail": "error object",
      "source": null,
      "meta": {
        "render": "form"
      }
    }
  ]
}

I'd rather not have all the null value keys returned from toArray(). Would implement such behavour break in some way the functionality of the class?

RelationshipsValidator::checkKey($key) doesn't check if key is allowed

Differently to what is done in AttributesValidator::checkKey(), the same method in RelationshipsValidator class doesn't check if the key is allowed.

I whould fix the checkKey() as follow in the RelationshipsValidator:

protected function checkKey($key)
{
    if (!$this->hasValidator($key) || !$this->isAllowedKey($key)) {
        $this->error(static::ERROR_UNRECOGNISED_RELATIONSHIP)
            ->source()
            ->setPointer(sprintf('/%s', $key));
    }

    return $this;
}

Inject error repository into `AbstractAuthorizer` by default

As best practice is to create errors via an instance of the ErrorRepositoryInterface, inject this into the AbstractAuthorizer by default.

Add a new trait to use instead of ErrorsAwareTrait that has an addError method that accepts either an ErrorInterface object or a string. If a string, will create the error from the repository. The method should return the error that was added so that methods such as setDetail can then be chained off it.

Expected Relationships/Attributes

If a ResourceObjectValidator has required relationships, but has not been set to expect relationships, then it will validate true if no relationships member is provided in input.

This is incorrect because if there are required relationships, there must be expected input. Need to fix this so that if there are required relationships then input must always be expected.

The same scenario will also exist for attributes - required vs expected.

Standard object iterator

The iterator on StandardObject does not recognise stdClass (as it is not a traversable).

This means whenever iterating over a standard object, it is always turned into an array. The problem here is that this means any nested objects are also converted into arrays, so the iteration value is not as expected.

See here:
https://github.com/cloudcreativity/json-api/blob/master/src/Object/StandardObject.php#L89-L96

It would be better to iterate, probably using a generator, and any values that are objects should be wrapped in a standard object. I.e. keep it consistent that objects are cast to the standard object interface.

This fix will however be breaking as it could have unintended consequences on existing code.

Detect message body in responses

At the moment the http_contains_body helper method does not correctly detect message body on a response. This is because the rules for a response having body are different from the rules for a request. For a response:

For response messages, whether or not a message-body is included with a message is dependent on both the request method and the response status code (section 6.1.1). All responses to the HEAD request method MUST NOT include a message-body, even though the presence of entity- header fields might lead one to believe they do. All 1xx (informational), 204 (no content), and 304 (not modified) responses MUST NOT include a message-body. All other responses do include a message-body, although it MAY be of zero length.
https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3

At the moment, the helper only applies the logic for a request - need to also add logic for a response.

Empty Relationships/Attributes Member

An empty relationships member should be accepted by ResourceObjectValidator even if there is no relationships validator set. I.e. the validator has been set up not to accept relationships, and although the client has included the member, it is empty so is acceptable.

The same applies to attributes.

Error collection HTTP status bug

The following:

{
    "errors": [
        {
            "status": "422",
            "code": "invalid-attributes",
            "title": "Invalid Attributes",
            "detail": "The provided attributes are invalid.",
            "source": {
                "pointer": "/data/attributes"
            }
        },
        {
            "status": "422",
            "code": "invalid-attribute",
            "title": "Invalid Attribute",
            "detail": "The title must be at least 2 characters.",
            "source": {
                "pointer": "/data/attributes/title"
            }
        }
    ]
}

had a HTTP status code of 400. Check what ErrorCollection::getStatus() returns in the above scenario.

Type error after client tries request to invalid URL

Getting this:

TypeError: Argument 1 passed to Neomerx\JsonApi\Exceptions\JsonApiException::addError() must implement interface Neomerx\JsonApi\Contracts\Document\ErrorInterface, null given, called in /home/cgammie/Development/cgammie/radio-poc/vendor/neomerx/json-api/src/Exceptions/JsonApiException.php on line 77

After using the guzzle client to submit a request when the URL is invalid (the base_uri option incorrectly set).

Badges

It will be much better to add badges (code coverage, code climate, dependencies) to this repo.
I think it will help to promote it and shows people stability of this lib.
I am also sure laravel-json-api should have such badges

Authorising updates needs access to what the client sent

When authorising update requests from the client, the authoriser requires access to what the client has sent (i.e. what the client is attempting to change). E.g. when authorising an update of a resource, the authorisation might be dependent on which resource attributes are being changed, as per this issue:
cloudcreativity/laravel-json-api#14

Two modifications are required to the AuthorizerInterface:

  1. canUpdate needs to receive a ResourceInterface object as its second parameter.
  2. canModifyRelationship needs to receive a RelationshipInterface object as its third parameter.

This is a breaking change so will have to be in v0.6

Allow packages to add configuration to API definitions

We have the need to add configuration to an API definition from multiple packages rather than a single configuration file. This is because we are composing APIs from separate Composer packages, that each need to add their configuration to a specific API's definition. This isn't a major change or too much added complexity - the interfaces just need to be updated to allow partial config to be added.

At the same time it would be good to rename Repositories to Factories. This is because the neomerx/json-api package uses the name Factory so it would be more consistent to follow the same pattern.

To do:

  • Rename CodecMatcherRepository to CodecMatcherFactory. Change the method signature to createCodecMatcher($apiNamespace, $schemas, $urlPrefix) for consistency. Move it to the Codec namespace as that is where it is in neomerx/json-api.
  • Codec matcher factory needs to support codecs per API definition and a defaults set, i.e. bring it inline with the schemas repository.
  • Need to be able to add partial configuration to the code matcher factory - i.e. add to the configuration.
  • Rename SchemasRepository to SchemaContainerFactory and change method signature to createSchemaContainer($apiNamespace). Move to the Schema namespace as that is where it is in neomerx/json-api.
  • Need to be able to add partial configuration to the schemas factory - i.e. add to the configuration.
  • Need a store factory that builds a store for a specific API. Again, the config needs to follow the same pattern of defaults for adapters to apply to all stores, and then adapters per store. Factory should be in the Store namespace for consistency.

Deprecate Throwable Error

ThrowableError isn't really useful because Exception::getCode() is final so cannot be overridden to provide an actual JSON API code.

Solution: deprecate ThrowableError and instead allow the first argument in ErrorException to be an array that is cast to an ErrorObject instance.

the place where I can save the result of any query

I'm trying to save the result of any query inside the key in the cache and add middle ware where I can check if
the key already exist inside the cache and if it is return it otherwise go further to the api

Validation Exception

Instead of 422 responses with validation error messages. I always get this.

CloudCreativity\LaravelJsonApi\Exceptions\ValidationException: JSON API error in file /Library/WebServer/Documents/omega_mcs_api/vendor/cloudcreativity/laravel-json-api/src/Exceptions/ValidationException.php on line 49

Expecting this:

'''
{
"errors": [
{
"status": "422",
"title": "Unprocessable Entity",
"detail": "The content field is required.",
"source": {
"pointer": "/data"
}
}
]
}
'''

Incorrect message detail in HasOneValidator

The following error message from a HasOneValidator is not adding the relationship name to the detail member:

{
    "status": "400",
    "code": "required",
    "title": "Required Relationship",
    "detail": "Missing required relationship \"%s\".",
    "source": {
        "pointer": "\/data\/relationships\/application"
    }
}

Bug in ResourceObjectValidator

ResourceObjectValidator::getKeyValidator() assumes that both the attributes and relationships validators are keyed validators. But one or both might not be.

It needs to only attempt to get a keyed validator from either one if they are keyed validators. If not, it should ignore them.

Update codec matcher config structure.

Amend condec matcher repository config structure to this:

    Config::NAME => [

        Config::CODEC_MATCHERS => [
            Codec::DEFAULTS => [
                Codec::ENCODERS => [
                    Codec::MEDIA_TYPES => [
                        'application/vnd.api+json' => null,
                        'application/vnd.api+json;charset=utf-8' => null,
                        'text/plain' => 'humanized',
                    ],
                    Codec::SCHEMAS => null,
                ],
                Codec::DECODERS => [
                    Codec::MEDIA_TYPES => [
                        'application/vnd.api+json' => null,
                        'application/vnd.api+json;charset=utf-8' => null,
                    ],
                ],
            ],
            'foo' => [
                Codec::ENCODERS => [
                    Codec::SCHEMAS => 'foo',
                ],
            ],
        ],

        Config::ENCODERS => [
            Enc::OPTIONS => [
                EncOpt::DEFAULTS => [
                    'options' => JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_TAG,
                ],
                'humanized' => [
                    'options' => JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES,
                ],
            ],
            Enc::SCHEMAS => [
                'foo' => [
                    // foo set of schemas here.
                ],
            ],
        ],

        Config::DECODERS => [
            'document' => DocumentDecoder::class,
            'object' => ObjectDecoder::class,
            'array' => ArrayDecoder::class,
        ],
    ],

Default resource document and relationship document validators

Validation of content sent by a client actually needs to pass two questions:

  1. Is it valid according to the JSON API specification? I.e. is it semantically and structurally correct?
  2. Is it logically valid? I.e. is it acceptable from a business logic perspective.

At the moment the two are being mixed and it is not possible to check one, then the other. There are instances where it may be necessary to check (1) but not (2) - therefore there is a need to construct a validator that checks a document for (1).

This framework agnostic library should be able to do this because (1) is about validating against the spec. To do this:

  • ValidatorProviderInterface needs to be return a validator for validating a resource document conforms to the JSON API spec.
  • ValidatorFactoryInterface::resourceDocument needs its parameter to be optional and if not provided, would use a validator that checks the resource conforms to the JSON API spec.
  • ValidatorFactoryInterface::relationshipDocument needs its parameter to be optional and if not provided, would use a validator that checks the relationship is either a valid has-one or has-many relationship.
  • Relationships validator should be able to structurally pass a relationships object regardless of whether there is a validator for each key. I.e. if there is not a has-one or has-many validator for a key, then it should just check that it is either. Likewise it does not need to know the expected type - can just check that the identifier or identifiers all have types and ids in them.

Has one validator bug

If the type member of the has-one identifier is invalid, the callback to validate the identifier is still being called.

RelationshipsValidator does not observe allowed keys

Currently RelationshipsValidator does not use isAllowedKey in the protected checkKey method. This is a bug because the decision of whether a key should be accepted should be down to whether it is allowed, not whether there is a validator for it (the current situation).

Complex attribute values validation?

Hello!

While using getResourceObject from the JsonApiController I haven't been successful to validate JSON object attribute values whereas with Arrays ones it's working without any issue. I'll show you a couple of examples.

Array value validation:

// Validation rules
protected $rules = [
    "numbers" => ["array"],
    "numbers.0" => ["integer"],
    "numbers.1" => ["integer"],
];

// Request content
{
    "data": {
        "type": "users",
        "attributes": {
            "numbers": ["123456789","987654321"]
        }
    }
}

// Everything works like a charm

JSON object value validation:

// Validation rules
protected $rules = [
    //"objects" => ["array"],
    "objects.attr1" => ["integer"],
    "objects.attr2" => ["integer"],
];

// Request content
{
    "data": {
        "type": "users",
        "attributes": {
            "objects": {
                "attr1": "123456789",
                "attr2": "987654321"
            }
        }
    }
}

// Makes me a sad panda

In fact, in the second example if I uncomment this line: //"objects" => ["array"], I'll get an error on the objects attribute value as it's not an array and I'm not able to access the attr1 and attr2 with dot notation because of the same reason.

Is there a specific way to declare the rules to validate JSON objects attribute values or is there any other way to go about this? maybe consider transforming every object position inside "attributes" into arrays so the default dot notation validation way works?

Add Date type validator

Add a date type validator. This should by default accept ISO8601 date formats, but the format(s) accept should be configurable per instance.

Invalid resource type in relationship

If a client submits a relationship with a resource type that the store does not recognise, a 500 error is caused by the following:

[2016-09-17 12:04:35] testing.ERROR: exception 'CloudCreativity\JsonApi\Exceptions\RuntimeException' with message 'No adapter for resource type: order' in [...]/vendor/cloudcreativity/json-api/src/Store/Store.php:144

Search All and Search Related

There is a need to introduce a search interface to encapsulate logic around searching resources and searching resources that are related to a primary resource.

Detail

Searching Primary Resources

The JSON API spec allows for resources to be retrieved via a GET request to the resource route. E.g. for a posts resource, the request can be to GET /posts. This route may support filtering, pagination, sorting, etc. The response may be a resource collection (or an empty resource collection) or a singular resource (or null if no matching singular resource).

Searching Related Resources

The JSON API spec allows for the retrieval of resources that are related to a primary resource. The related resources may be a has-one or has-many relationship.

For example, a posts resource with a has-one author relationship to a users resource. GET /posts/1/author gets the related users resource. GET /posts/1/relationships/author gets the resource identifier of the related users resource.

For example, a posts resource with a has-many comments relationship. GET /posts/1/comments gets the related comments resources. GET /posts/1/relationships/comments gets a resource identifier collection of the related comments resources.

For these has-many relationships the server may support filtering, pagination, sorting etc. E.g. if the comments relationship was to support a since filter, then GET /posts/1/comments?filter[since]=2017-01-01 would return all comments related to post 1 that were created since the supplied date.

Problems

It cannot be assumed that the paginating, filtering, sorting etc strategies for a resource type and its relationships are the same. For example, the filter parameters allowed for searching posts resources are likely to be different from those allowed when filtering the comments relationship for a specific post. The same may equally be true for sorting, pagination, allowed include paths etc.

At the moment, the "unit" that contains the logic as to what request parameters a server supports for a specific resource type is the RequestHandlerInterface class. At the moment this is only designed for processing requests for the primary resource (e.g. the posts resource) and does not allow variation of allowed parameters based on whether the request is for the primary resource or one of its relationships.

An additional problem is that the paging strategy is defined at the API level. However, paging strategies may vary across resource types, as well as within relationships. For instance, the posts resource collection might be paginated using page-based number and size parameters, but the comments relationship might be paginated using cursor based pagination.

The current pagination solution assumes that there are two pagination parameters, but this may not be the case. It does not allow rejection of a paging request if for instance the client asks for more than the maximum number of resources per page.

Proposed Solution

The logic for searching resources is complex and is linked directly to the resource type that owns the endpoints. To follow this package's pattern of encapsulating complex logic into isolated units, it is proposed that a SearchInterface is created, with the implementing class containing the logic for searching a specific resource type and its relationships. This would have two methods on it:

  • searchAll(EncodingParametersInterface $params) - to search the primary resource (e.g. posts)
  • searchRelated($record, $relationship, EncodingParametersInterface $params) - e.g. to search the comments relationship of a specific posts record.

The following additional changes are proposed:

  1. The ChecksQueryParameters trait must be modified so that the request handler can validate inbound parameters based on whether the primary resource or one of its relationships is being searched.

  2. Validation of sort, filter, page should only occur if the request is to a search endpoint, rather than on all endpoints as is the current case.

  3. The filterValidator method on the validator provider needs an additional argument of the relationship being searched (or null if searching the primary resource) so that it can vary its rules based on whether a relationship is being searched or not.

  4. Remove the PagingStrategyInterface and PaginatorInterface as logic around pagination can be held within the search class.

  5. Add a pageValidator method to the validator provider, following same pattern as filterValidator. This would allow the page params to be validated, which in frameworks such as Laravel means actual validation rules could be used. Add a PageValidatorInterface along the same lines as the FilterValidatorInterface.

Pagination on relationships

In the User/Posts example:
Imagine I want to present the User all his Posts.
I could return $user->posts, but there are lots of posts for each user, so I want to paginate them.

From my research, there is nothing like this available in laravel. (If there is, please let me know!)
I think it would be a really good feature if it's not planned yet.

CloudCreativity\JsonApi\Error\ThrowableError should allow an independent code

I've been playing around with this package using both the CloudCreativity\JsonApi\Error\ThrowableError and the CloudCreativity\JsonApi\Error\ErrorObject classes to try implementing JWT authentication exception and error responses but I noticed a radical difference between both of em.

ThrowableError doesn't seem to use a provided "code" key in the array sent to its constructor's first parameter (CloudCreativity\JsonApi\Error\ThrowableError line: 76), I can use a separate $code parameter but it allows only null|integer values, which goes against JSON API standard as stated on their specification: code: an application-specific error code, expressed as a string value.

I believe ThrowableError should not use the same code that's being used for the exception code and allow for a different application's specific code to be added which should be treated as a string and rendered on the response.

What do you think?

Belongs To Validation Error

The following passes validation:

{
    "data": { "type": "foo" }
}

i.e. no id member, so this identifier is invalid.

Validation of resource identifier with empty id

[2017-05-17 06:10:53] testing.ERROR: exception 'CloudCreativity\JsonApi\Exceptions\RuntimeException' with message 'Id member is not a string or integer.' in /vagrant/vendor/cloudcreativity/json-api/src/Object/Helpers/IdentifiableTrait.php:86
Stack trace:
#0 /vagrant/vendor/cloudcreativity/json-api/src/Object/ResourceIdentifier.php(105): CloudCreativity\JsonApi\Object\ResourceIdentifier->getId()
#1 /vagrant/vendor/cloudcreativity/json-api/src/Store/IdentityMap.php(102): CloudCreativity\JsonApi\Object\ResourceIdentifier->toString()
#2 /vagrant/vendor/cloudcreativity/json-api/src/Store/IdentityMap.php(73): CloudCreativity\JsonApi\Store\IdentityMap->lookup(Object(CloudCreativity\JsonApi\Object\ResourceIdentifier))
#3 /vagrant/vendor/cloudcreativity/json-api/src/Store/Store.php(73): CloudCreativity\JsonApi\Store\IdentityMap->exists(Object(CloudCreativity\JsonApi\Object\ResourceIdentifier))
#4 /vagrant/vendor/cloudcreativity/json-api/src/Validators/AbstractRelationshipValidator.php(103): CloudCreativity\JsonApi\Store\Store->exists(Object(CloudCreativity\JsonApi\Object\ResourceIdentifier))
#5 /vagrant/vendor/cloudcreativity/json-api/src/Validators/AbstractRelationshipValidator.php(311): CloudCreativity\JsonApi\Validators\AbstractRelationshipValidator->doesExist(Object(CloudCreativity\JsonApi\Object\ResourceIdentifier))
#6 /vagrant/vendor/cloudcreativity/json-api/src/Validators/AbstractRelationshipValidator.php(192): CloudCreativity\JsonApi\Validators\AbstractRelationshipValidator->validateExists(Object(CloudCreativity\JsonApi\Object\ResourceIdentifier), 'ticket-type')
#7 /vagrant/vendor/cloudcreativity/json-api/src/Validators/RelationshipValidator.php(48): CloudCreativity\JsonApi\Validators\AbstractRelationshipValidator->validateHasOne(Object(CloudCreativity\JsonApi\Object\Relationship), NULL, 'ticket-type', Object(CloudCreativity\JsonApi\Object\Resource))
#8 /vagrant/vendor/cloudcreativity/json-api/src/Validators/RelationshipsValidator.php(211): CloudCreativity\JsonApi\Validators\RelationshipValidator->isValid(Object(CloudCreativity\JsonApi\Object\Relationship), NULL, 'ticket-type', Object(CloudCreativity\JsonApi\Object\Resource))
#9 /vagrant/vendor/cloudcreativity/json-api/src/Validators/RelationshipsValidator.php(157): CloudCreativity\JsonApi\Validators\RelationshipsValidator->validateRelationship('ticket-type', Object(CloudCreativity\JsonApi\Object\Relationships), Object(CloudCreativity\JsonApi\Object\Resource), NULL)
#10 /vagrant/vendor/cloudcreativity/json-api/src/Validators/ResourceValidator.php(234): CloudCreativity\JsonApi\Validators\RelationshipsValidator->isValid(Object(CloudCreativity\JsonApi\Object\Resource), NULL)
#11 /vagrant/vendor/cloudcreativity/json-api/src/Validators/ResourceValidator.php(111): CloudCreativity\JsonApi\Validators\ResourceValidator->validateRelationships(Object(CloudCreativity\JsonApi\Object\Resource), NULL)
#12 /vagrant/vendor/cloudcreativity/json-api/src/Validators/ResourceDocumentValidator.php(79): CloudCreativity\JsonApi\Validators\ResourceValidator->isValid(Object(CloudCreativity\JsonApi\Object\Resource), NULL)
#13 /vagrant/vendor/cloudcreativity/json-api/src/Http/Requests/RequestFactory.php(140): CloudCreativity\JsonApi\Validators\ResourceDocumentValidator->isValid(Object(CloudCreativity\JsonApi\Object\Document))
#14 /vagrant/vendor/cloudcreativity/json-api/src/Http/Requests/RequestFactory.php(127): CloudCreativity\JsonApi\Http\Requests\RequestFactory->validateDocument(Object(CloudCreativity\JsonApi\Object\Document), Object(CloudCreativity\LaravelJsonApi\Http\Requests\RequestInterpreter))

Believe the data submitted was a has-one relationship with data object that had correct type but id was a null value.

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.