Giter Site home page Giter Site logo

cactoos-http's Introduction

Donate via Zerocracy

EO principles respected here Managed by Zerocracy DevOps By Rultor.com We recommend IntelliJ IDEA

Build Status Javadoc PDD status Maven Central License

Test Coverage SonarQube

Cactoos-HTTP is a experimental HTTP client, fully object-oriented.

These are the design principles behind Cactoos-HTTP.

All you need is this:

<dependency>
  <groupId>org.cactoos</groupId>
  <artifactId>cactoos-http</artifactId>
  <version><!-- Get it here: https://github.com/yegor256/cactoos-http/releases --></version>
</dependency>

Java version required: 1.8+.

StackOverflow tag is cactoos.

We are well aware of competitors (most likely they are more powerful than our client, but less object-oriented):

How to use

Ht stands for HTTP. We are not using Http just in order to look a bit different than all other libraries.

To make a simple HTTP GET request and read its body:

String body = new TextOf(
  new HtBody(
    new HtResponse(
      "http://www.google.com"
    )
  )
).asString();

This one sends a PUT request with a multi-part form and reads back some headers and the response code (mind the usage of StickyInput):

Input head = new StickyInput(
  new HtHead(
    new HtResponse(
      new HtWire("www.example.com"),
      new Joined(
        "\n\r",
        "PUT / HTTP/1.1",
        "Host: www.example.com"
      ).asString()
    )
  )
);
int status = new HtStatus(head).intValue();
Map<String, String> headers = new HtHeaders(head);

Questions

Ask your questions related to cactoos library on Stackoverflow with cactoos tag.

How to contribute?

Just fork the repo and send us a pull request.

Make sure your branch builds without any warnings/issues:

mvn clean install -Pqulice

License (MIT)

Copyright (c) 2018 Yegor Bugayenko

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

cactoos-http's People

Contributors

baybatu avatar dgroup avatar golyalpha avatar iakunin avatar ilyakharlamov avatar krzyk avatar llorllale avatar ocristian avatar paulodamaso avatar renovate[bot] avatar rultor avatar scristalli avatar victornoel avatar vssekorin avatar vzurauskas avatar yegor256 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cactoos-http's Issues

Simple requests

I think there should be some simple request objects, like:

new HtResponse(
  new RqSimple("GET", "https://foo.bar?param=1")
);
// or
new HtResponse(
  new RqSimple.Get("https://foo.bar?param=1")
);

HtTimedWire

Let's create a Wire decorator, which will terminate the connection if it's taking too long.

EO violation in Wire?

Into the Wire interface we have a method Input send(Input input) throws IOException, but it isn't a EO violation? In EO vol 1, Yegor says "verb methods should return nothing (void)" and send() is a verb. So, should we rename it? My suggestion: Input response(Input request) throws IOException.

Update cactoos to 0.39

This is just a marker issue to update cactoos to 0.39.
It's not a minor change, since new version of cactoos introduces lots of checked exceptions to the method signatures for some reason.

HtUpgradeWire.java:32-45: min As discovered in #53, the...

The puzzle 23-e7afac42 from #23 has to be resolved:

* @todo #23:30 min As discovered in #53, the upgrade is not a job of the
* wire because it need reading the contents of the response (in this case,
* status code). So, this feature would be under the responsibility of a
* response-like object. It must be implemented someway like this:
* new HtUpgradedResponse(
* new IterableOf&lt;&gt;(
* new MapEntry&lt;Func&lt;String, Boolean&gt;, Func&lt;URI, Wire&gt;&gt;(
* upgrade -&gt; upgrade.contains("TLS"),
* HtSecureWire::new
* )
* )
* )
* The test HtUpgradeWireTest#testHtUpgrade must be removed after the
* implementation of this class.

The puzzle was created by rultor on 30-May-18.

Estimate: 30 minutes,

If you have any technical questions, don't ask me, submit new tickets instead. The task will be "done" when the problem is fixed and the text of the puzzle is removed from the source code. Here is more about PDD and about me.

LimitedInputStream

We need LimitedInputSteam that get bytes until some specific bytes.

  • public BoundedInputStream(final InputStream stream, final Bytes limiter)
  • public BoundedInputStream(final InputStream stream, final byte[] limiter)

For example, this can be useful for #4
Example:

new BounedInputStream(
    new InputStreamOf("123456789"),
    new BytesOf("56")
)

> "1234"

Few configuration issues (for cactoos-http)

(This is exactly the same as in yegor256/cactoos#815, I don't know if we need two issues, but the repos are separate so I created this also).

  1. .travis.yml:
  • we don't need gem install est (and do we need xcop?, I don't see it used anywhere)
  • script should have pdd --source=$(pwd) --verbose --file=/dev/null (just like in .rultor.yml) to catch PDD errors early
  • mvn clean site -Psite --errors --batch-mode should be after mvn clean install ...
  1. .rultor.yml:
  • -XX:MaxPermSize=256m should be removed (it is not used by java 8)
  • architects section should have llorllale first (so he will asked by rultor after reviewer does @rultor merge)
  • pdd --source=$(pwd) --verbose --file=/dev/null should be first in the merge part (to catch PDD errors early without doing long maven build)
  • do we need sudo gem install --no-rdoc --no-ri xcop?

And general question, do we deploy the result of mvn site anywhere? It is build in both rultor and travis, but I don't know if there is a point in doing two almost full maven builds if we don't put the site anywhere.

HtHead can be broken.

Now HtHead reads block, then checks it. Therefore, the situation is possible:
... \r\n - block 1
\r\n ... - block 2
In this case, HtHead#stream does not find \r\n\r\n.

HtKeepAliveResponse.java:58-66: Replace the HtWire by...

The puzzle 20-eb4af059 from #20 has to be resolved:

* @todo #20:30min Replace the HtWire by HtKeepAliveWire which should
* support the <em>Keep-Alive</em> header. It should has at least 1 `ctor`
* with 3 parameters:
* - `wire` which represents the HTTP connection;
* - `timeout` in milliseconds;
* - `rmax` the max quantity of within the timeout.
* In case the quantity of requests is greater than rmax but takes less
* time than `timeout`, the connection should be reset by the server.
* Remove the suppresing of PMD errors due to unused private fields.

The puzzle was created by @rultor on 07-Feb-19.

If you have any technical questions, don't ask me, submit new tickets instead. The task will be "done" when the problem is fixed and the text of the puzzle is removed from the source code. Here is more about PDD and about me.

IllegalArgumentException: port is -1

Exception in thread "main" java.lang.IllegalArgumentException: port out of range:-1
	at java.net.InetSocketAddress.checkPort(InetSocketAddress.java:143)
	at java.net.InetSocketAddress.<init>(InetSocketAddress.java:224)
	at java.net.Socket.<init>(Socket.java:211)
	at org.cactoos.http.HtWire.send(HtWire.java:89)
	at org.cactoos.http.HtResponse.stream(HtResponse.java:98)
	at org.cactoos.io.TeeInput.stream(TeeInput.java:870)
	at org.cactoos.io.InputAsBytes.asBytes(InputAsBytes.java:79)
	at org.cactoos.io.BytesOf.asBytes(BytesOf.java:346)
	at org.cactoos.text.TextOf.lambda$new$0(TextOf.java:296)
	at org.cactoos.scalar.IoCheckedScalar.value(IoCheckedScalar.java:70)
	at org.cactoos.text.TextOf.asString(TextOf.java:365)
	at org.cactoos.http.HtHead.stream(HtHead.java:63)
	at org.cactoos.http.Main.main(Main.java:10)

Example: new HtHead(new HtResponse("http://www.google.com")).stream();

HtStatus.java:37-40: The implementation here is not...

The puzzle 1-6a67a5c8 from #1 has to be resolved:

* @todo #1:30min The implementation here is not effective. It converts
* the entire head part of the request to a string and then only
* takes the first line out of it. We should deal with a stream
* instead and just read its first line.

The puzzle was created by Yegor Bugayenko on 04-Apr-18.

Estimate: 30 minutes, role: DEV.

If you have any technical questions, don't ask me, submit new tickets instead. The task will be "done" when the problem is fixed and the text of the puzzle is removed from the source code. Here is more about PDD and about me.

Not correct example in Read.me

In first example

String body = new TextOf(
new HtBody(
new HtResponse(
"http://www.google.com",
"GET / HTTP/1.1"
)
)
).asString();

This code is doesn't compile, as I understood it should be replaced to

String body = new TextOf(
new HtBody(
new HtResponse(
new HtWire("http://www.google.com"),
"GET / HTTP/1.1"
)
)
).asString();

Upgrade qulice to 0.17.3

New qulice version brings following important changes:

  • removal of @author tag (it is prohibited now)
  • removal of @version tag (it is prohibited now)
  • license header should start with /* instead of /** - this will fix problem with IntelliJ reporting it as a javadoc that is not attached to any class
  • checkstyle validation performance improvement (speedup of ~ 10%)
    And few minor formatting changes.

Please upgrade the qulice and fix the new problems found.

HtContentType

Let's create a reader of response content-type:

Scalar<String> type = new HtContentType(
  new HtHead(new HtResponse("http://www.google.com"))
).value();

BoundedByteBuffer copies array every time when full.

In current implementation when BoundedByteBuffer is full then it going to copy full array on every offer operation. So complexity of BoundedByteBuffer.offer() is O(n)

But we can avoid any copy. Just look how ArrayDeque works inside:

    public void addFirst(E e) {
        if (e == null)
            throw new NullPointerException();
        elements[head = (head - 1) & (elements.length - 1)] = e;
        if (head == tail)
            doubleCapacity();
    }

Looks a bit complex but idea is very nice. They use one trick: elements.length is always a power of two. So (head -1) & (elements.length - 1) just drops higher bits of head -1. So when head-1 become less than 0, then a head start to count from the elements.length-1. And so on in a circle.

In case if elements.length is not a power of two then we should use x % elements.length for making such circle.

Example in our case:
elements = {0, 0, 0};
this.idx = 0;
this.full = false;

  1. Add 1:
    elements == {1, 0, 0}
    this.idx = ((this.idx + 1) % 3) = 1;
    this.full == false;
  2. Add 2:
    elements == {1, 2, 0}
    this.idx = ((this.idx + 1) % 3) = 2;
    this.full == false;
  3. Add 3:
    elements == {1, 2, 3}
    this.idx = ((this.idx + 1) % 3) = 0;
    this.full = true;
  4. Add 4:
    elements == {4, 2, 3}
    this.idx = ((this.idx + 1) % 3) = 1;
    this.full == true;

And then offer become O(1).

Then if we want to read there are two options:

  1. If this.full == false: just read from 0 to this.idx,
  2. If this.full == true: read from this.idx+1 to elements.size then read from 0 to this.idx.

HtCookies.java:46-48: The implementation of method...

The puzzle 8-4e75a126 from #8 has to be resolved:

* @todo #8:30min The implementation of method stream() will break on
* "flag-type" directives (`Secure`, `HttpOnly`). Fix HtHeaders so that
* these directives are handled correctly.

The puzzle was created by rultor on 05-May-18.

Estimate: 30 minutes,

If you have any technical questions, don't ask me, submit new tickets instead. The task will be "done" when the problem is fixed and the text of the puzzle is removed from the source code. Here is more about PDD and about me.

HtAutoRedirect

Let's create HtAutoRedirect, which will encapsulate HtResponse and make another request if its status code is 30x:

String body = new TextOf(
  new HtBody(new HtAutoRedirect(new HtResponse("http://www.google.com")))
).asString();

Upgrade mechanism

The wire should be able to upgrade connection on 101 status code, e.g. this head

HTTP/1.1 101 Switching Protocols
Upgrade: TLS/1.0, HTTP/1.1

should switch the wire to https protocol.

Configure javadoc generation

To make sure that we don't make mistakes in javadoc configuration please add a javadoc generation phase to travis and rultor config (it should be before the main build phase):

mvn javadoc:javadoc

To do this we need to configure the plugin to allow our custom tags (@checkstyle and @todo), without those right now the javadoc generation fails.

Inconsistent, non-OO or non-declarative tests should be improved

I noticed during my last PR that the quality standards of cactoos-http's tests are not at their best.

In particular we have many different ways of asserting facts depending on the test class:

  • Matchers.equalTo() or new EqualTo() to check equality while most of the time InputHasContent or TextHasString would be perfect (see also yegor256/cactoos#836).
  • assertions on Map.get while Matchers.hasEntry (or its OO equivalent IsMapContaining) could make things more declarative.
  • calls to Scalar.value() while SclaraHasValue could be used.
  • we should prefer using the Matcher's class constructor instead of the static factory method from Matchers. For example use new StringEndsWith() instead of Matchers.endsWith().

I propose to fix this as soon as possible before cactoos-http becomes bigger and it becomes cumbersome to fix all those problems.

SkipInput.java:90-95: this internal class should be...

The puzzle 3-25734ac4 from #3 has to be resolved:

* @todo #3:30min this internal class should be transformed to a full
* fledged public class with a clear interface, either in the cactoos or
* the cactoos-http project and the implementation is not efficient in
* memory usage because of the boxing of bytes into an object. This should
* be replaced by a real circular byte buffer implementation with
* primitive bytes.

The puzzle was created by Victor Noël on 21-Apr-18.

Estimate: 30 minutes,

If you have any technical questions, don't ask me, submit new tickets instead. The task will be "done" when the problem is fixed and the text of the puzzle is removed from the source code. Here is more about PDD and about me.

HtBody.java:39-44: The implementation of method stream()...

The puzzle 1-94e51014 from #1 has to be resolved:

* @todo #1:30min The implementation of method stream() is less than
* effective, because it reads the entire content of the response, turning
* it into text and then splitting. What if the content is binary and
* can't be converted to string? What if the content is super big
* and must be presented as an stream, not a piece of text. Let's fix
* it.

The puzzle was created by Yegor Bugayenko on 04-Apr-18.

Estimate: 30 minutes, role: DEV.

If you have any technical questions, don't ask me, submit new tickets instead. The task will be "done" when the problem is fixed and the text of the puzzle is removed from the source code. Here is more about PDD and about me.

pom.xml:165-166: we should re-enable findbugs and fix all...

The puzzle 49-d03f4828 from #49 has to be resolved:

cactoos-http/pom.xml

Lines 165 to 166 in aa4c078

@todo #49:30min we should re-enable findbugs and fix all problems it detects.
This mainly concerns for now reliance on default encoding in HtStatus.

The puzzle was created by Victor Noël on 19-May-18.

Estimate: 30 minutes,

If you have any technical questions, don't ask me, submit new tickets instead. The task will be "done" when the problem is fixed and the text of the puzzle is removed from the source code. Here is more about PDD and about me.

HtWire hangs until connection is closed remotely

Test case:

new TextOf(
  new HtResponse(
    new HtWire("somehost"),
    "GET /some/resource HTTP/1.1\r\n" +
    "Host: somehost\r\n\r\n"
  )
).asString()

The code above will hang until the remote service sends a TCP packet with the FIN flag.

The fundamental question here is: how do we tell that we have already received the entire HTTP response and thus avoid having to wait until the remote service ends the connection themselves?

We can start with section 3.3.3 of RFC7230.

Edit: can be avoided by sending the Connection: close header (remote service needs to behave well; usually not a problem though)

Inefficient use of regexps

Following classes: HtBody, HtHead, HtHeaders and HtStatus are using String.split() which compiles the new line/double new line patterns multiple times.
This can be replaced with e.g. precompiling the Pattern and storing it in the class as a constant and later on using Pattern.split().

HtRetryWire

Let's create a new Wire decorator which will retry to make a connection a few times.

Ignore RegexpMultilineCheck

Now all classes do check on CRLF(\r\n), but RegexpMultilineCheck requires Unix-like end of line in files. Because of this, it is impossible to work with files. For example, to create a test for large text, as large-text.txt in cactoos.

I think we should ignore RegexpMultilineCheck in this project.

HtHeadTest.java:44-48: This test does not cover all...

The puzzle 1-06a076ae from #1 has to be resolved:

* @todo #1:30min This test does not cover all possible cases.
* https://codecov.io/gh/yegor256/cactoos-http/pull/24/diff?src=pr&el=tree
* #diff-c3JjL21haW4vamF2YS9vcmcvY2FjdG9vcy9odHRwL0h0U3RhdHVzLmphdmE=
* Finish covering all branches missed for this implementation.
* A refactor may be due as well.

The puzzle was created by rultor on 01-May-18.

Estimate: 30 minutes,

If you have any technical questions, don't ask me, submit new tickets instead. The task will be "done" when the problem is fixed and the text of the puzzle is removed from the source code. Here is more about PDD and about me.

HtHead.java:39-43: The implementation of method stream()...

The puzzle 1-97d18cdb from #1 has to be resolved:

* @todo #1:30min The implementation of method stream() is rather
* ineffective and defective. What if the content of the HTTP response
* is too big? Or is binary and can't be represented as a string?
* Instead of turning it into a string we must deal with a stream
* of bytes.

The puzzle was created by Yegor Bugayenko on 04-Apr-18.

Estimate: 30 minutes, role: DEV.

If you have any technical questions, don't ask me, submit new tickets instead. The task will be "done" when the problem is fixed and the text of the puzzle is removed from the source code. Here is more about PDD and about me.

HttpResponse PMD.AvoidDuplicateLiterals

/src/test/java/org/cactoos/http/HtResponseTest.java[60-60]: The String literal "HTTP/1.1 200 OK" appears 2 times in this file; the first occurrence is on line 60 (AvoidDuplicateLiterals)

HtCookies.java:42-45: The implementation of method...

The puzzle 8-0309755b from #8 has to be resolved:

* @todo #8:30min The implementation of method stream() can handle only
* one Set-Cookie in a response. Fix HtHeaders so that a single key
* may be mapped to one or more values (it is legal to receive more than one
* Set-Cookie in a response).

The puzzle was created by rultor on 05-May-18.

Estimate: 30 minutes,

If you have any technical questions, don't ask me, submit new tickets instead. The task will be "done" when the problem is fixed and the text of the puzzle is removed from the source code. Here is more about PDD and about me.

HtSecureWire

Let's implement SSL based Wire, to support https.

Use cactoos FormattedText instead of static String format.

There are few places in which we can replace static String format on FormattedText: org.cactoos.http.HtResponse, org.cactoos.http.HtWireTest, org.cactoos.http.HtSecureWireTest, org.cactoos.http.HtResponseTest, org.cactoos.http.HtAutoRedirectTest

findbugs errors in current master

While working on #9, running qulice gives me this error:

[WARNING] FindBugs: L D RCN: Redundant nullcheck of socket, which is known to be non-null in org.cactoos.http.HtWire.send(Input)  Redundant null check at HtWire.java:[line 102]
[WARNING] FindBugs: M B FS: Format string should use %n rather than \n in new org.cactoos.http.HtResponse(URI)  At HtResponse.java:[line 69]

Auto-detect host wire

It's not very convenient to write a host two times (first in wire, second in request):

final Wire wire = new HtWire("http://www.google.com");
new HtResponse(
  wire,
  "http://www.google.com", // same string
  "GET / HTTP/1.1"
)

I think a wire should be able to read host value from request Host header:

new HtResponse(
  new HtWire(),
  "http://www.google.com",
  "GET / HTTP/1.1"
)

HTTP/2 support

Does cactoos-http designed to support HTTP/2 protocol? If yes how does it share sockets (or clients) across requests?

HtResponse.java:39-42: We need decorators for HtResponse...

The puzzle 62-02593012 from #62 has to be resolved:

* @todo #62:30min We need decorators for HtResponse that will automatically
* close the inputstream (therefore also closing the network socket) based
* on criteria like the Content-Length header, the Transfer-Encoding header
* (when service returns the payload in chunks), etc.

The puzzle was created by George Aristy on 28-Jun-18.

Estimate: 30 minutes,

If you have any technical questions, don't ask me, submit new tickets instead. The task will be "done" when the problem is fixed and the text of the puzzle is removed from the source code. Here is more about PDD and about me.

HtWire.java:46-49: HtWire should not close the socket...

The puzzle 62-ec9a5ea7 from #62 has to be resolved:

* @todo #62:30min HtWire should not close the socket opened to the remote
* service (this includes not closing associated input and output streams).
* It should instead return an `Input` with the socket's inputstream "unread".
* Refactor accordingly.

The puzzle was created by George Aristy on 28-Jun-18.

Estimate: 30 minutes,

If you have any technical questions, don't ask me, submit new tickets instead. The task will be "done" when the problem is fixed and the text of the puzzle is removed from the source code. Here is more about PDD and about me.

HtCookies

Let's create class HtCookies (implements Map<String,String>) to read cookies from HTTP response:

String cookie = new HtCookies(
  new HtHead(new HtResponse("http://www.google.com"))
).get("user");

Broken example with PUT in readme

Example is broken

Input head = new StickyInput(
  new HtHead(
    new HtResponse(
      new HtWire("www.example.com"),
      new JoinedText(
        "\n\r"
        "PUT / HTTP/1.1",
        "Host: www.example.com"
      )
    )
  )
);
int status = HtStatus(head).intValue();
Map<String, String> headers = new HtHeaders(head);

Need new HtStatus(head) instead HtStatus(head), comma after "\n\r" is missing, need to call asString for JoinedText.

Replace HtBody, HtStatus and HtHead with a unique object for the whole HTTP message

This is just an idea, but looking at #3 or #4, I can see that an HTTP message is meant to be a whole stream.

What if we had an object, HtMessage, that provides head(), body() and so on to take care of this fact? It would solve the performance problems that seem to be clearly interrelated as well as make things clearer about the reality of what an HTTP message is.

build failed with openjdk11

os: linux mint, windows 10
maven 3.6.0
openjdk11

/cactoos-http/src/main/java/org/cactoos/http/HtCookies.java:[56,50] no suitable constructor found for SplitText(java.lang.Object,java.lang.String)
[ERROR] constructor org.cactoos.text.SplitText.SplitText(java.lang.String,java.lang.String) is not applicable
[ERROR] (argument mismatch; java.lang.Object cannot be converted to java.lang.String)
[ERROR] constructor org.cactoos.text.SplitText.SplitText(java.lang.String,org.cactoos.Text) is not applicable
[ERROR] (argument mismatch; java.lang.Object cannot be converted to java.lang.String)
[ERROR] constructor org.cactoos.text.SplitText.SplitText(org.cactoos.Text,java.lang.String) is not applicable
[ERROR] (argument mismatch; java.lang.Object cannot be converted to org.cactoos.Text)
[ERROR] constructor org.cactoos.text.SplitText.SplitText(org.cactoos.Text,org.cactoos.Text) is not applicable
[ERROR] (argument mismatch; java.lang.Object cannot be converted to org.cactoos.Text)
[ERROR] constructor org.cactoos.text.SplitText.SplitText(org.cactoos.text.UncheckedText,org.cactoos.text.UncheckedText) is not applicable
[ERROR] (argument mismatch; java.lang.Object cannot be converted to org.cactoos.text.UncheckedText)
[ERROR] /home/admin/Projects/java/cactoos-http/src/main/java/org/cactoos/http/HtCookies.java:[53,32] incompatible types: bad return type in lambda expression
[ERROR] cannot infer type arguments for org.cactoos.map.Grouped<>
[ERROR] reason: inference variable Y has incompatible bounds
[ERROR] equality constraints: java.lang.Iterable<java.lang.Object>
[ERROR] lower bounds: org.cactoos.text.SplitText

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.