diff --git a/src/main/java/org/takes/facets/previous/RsPrevious.java b/src/main/java/org/takes/facets/previous/RsPrevious.java
new file mode 100644
index 000000000..723f45d74
--- /dev/null
+++ b/src/main/java/org/takes/facets/previous/RsPrevious.java
@@ -0,0 +1,60 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014-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.
+ */
+package org.takes.facets.previous;
+
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.takes.Response;
+import org.takes.rs.RsWithCookie;
+import org.takes.rs.RsWrap;
+
+/**
+ * Response decorator, with a link to previous page.
+ *
+ *
The class is immutable and thread-safe.
+ *
+ * @author Yegor Bugayenko (yegor256@gmail.com)
+ * @version $Id$
+ * @since 1.10
+ */
+@ToString(callSuper = true)
+@EqualsAndHashCode(callSuper = true)
+public final class RsPrevious extends RsWrap {
+
+ /**
+ * Ctor.
+ * @param rsp Response to decorate
+ * @param location The location user is trying to access
+ */
+ public RsPrevious(final Response rsp, final String location) {
+ super(
+ new RsWithCookie(
+ rsp,
+ TkPrevious.class.getName(),
+ location
+ )
+ );
+ }
+
+}
diff --git a/src/main/java/org/takes/facets/previous/TkPrevious.java b/src/main/java/org/takes/facets/previous/TkPrevious.java
new file mode 100644
index 000000000..1841dbaf0
--- /dev/null
+++ b/src/main/java/org/takes/facets/previous/TkPrevious.java
@@ -0,0 +1,81 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014-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.
+ */
+package org.takes.facets.previous;
+
+import java.io.IOException;
+import java.util.Iterator;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.takes.Request;
+import org.takes.Response;
+import org.takes.Take;
+import org.takes.rq.RqCookies;
+import org.takes.rs.RsRedirect;
+import org.takes.rs.RsWithCookie;
+
+/**
+ * Take that redirects to previous URL
+ *
+ *
The class is immutable and thread-safe.
+ *
+ * @author Yegor Bugayenko (yegor256@gmail.com)
+ * @version $Id$
+ * @since 1.10
+ */
+@ToString
+@EqualsAndHashCode
+public final class TkPrevious implements Take {
+
+ /**
+ * Original take.
+ */
+ private final Take origin;
+
+ /**
+ * Ctor.
+ * @param take Original take
+ */
+ public TkPrevious(final Take take) {
+ this.origin = take;
+ }
+
+ @Override
+ public Response act(final Request req) throws IOException {
+ final Iterator cookies = new RqCookies.Base(req)
+ .cookie(TkPrevious.class.getName())
+ .iterator();
+ final Response response;
+ if (cookies.hasNext()) {
+ response = new RsWithCookie(
+ new RsRedirect(cookies.next()),
+ TkPrevious.class.getName(),
+ ""
+ );
+ } else {
+ response = this.origin.act(req);
+ }
+ return response;
+ }
+
+}
diff --git a/src/main/java/org/takes/facets/previous/package-info.java b/src/main/java/org/takes/facets/previous/package-info.java
new file mode 100644
index 000000000..3f1d5ce15
--- /dev/null
+++ b/src/main/java/org/takes/facets/previous/package-info.java
@@ -0,0 +1,50 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014-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.
+ */
+
+/**
+ * Previous.
+ *
+ * These classes may be useful when you want to redirect your user
+ * to some location and remember what he/she wanted to see before. This
+ * is especially useful during login. When the user is trying to open
+ * some page, where access credentials are required, you throw
+ * {@link org.takes.facets.forward.RsForward} to the home page,
+ * with this class inside, with the original URL:
+ *
+ *
if (not_logged_id) {
+ * throw new RsForward(
+ * new RsWithPrevious(
+ * new RsFlash("You must be logged in!")
+ * )
+ * );
+ * }
+ *
+ * Then, you decorate your application with
+ * {@link org.takes.facets.previous.TkPrevious} and that's it.
+ *
+ * @author Yegor Bugayenko (yegor256@gmail.com)
+ * @version $Id$
+ * @since 0.10
+ */
+package org.takes.facets.previous;
diff --git a/src/main/java/org/takes/rq/RqCookies.java b/src/main/java/org/takes/rq/RqCookies.java
index 70ff16d9f..84d17be6e 100644
--- a/src/main/java/org/takes/rq/RqCookies.java
+++ b/src/main/java/org/takes/rq/RqCookies.java
@@ -88,7 +88,7 @@ public Iterable cookie(final CharSequence key)
Collections.emptyList(),
new Sprintf(
// @checkstyle LineLengthCheck (1 line)
- "there are no Cookies by name \"%s\" among %d others: %s",
+ "There are no Cookies by name \"%s\" among %d others: %s",
key, map.size(), map.keySet()
)
);
@@ -96,7 +96,7 @@ public Iterable cookie(final CharSequence key)
iter = new VerboseIterable(
Collections.singleton(value),
new Sprintf(
- "there is always only one Cookie by name \"%s\"",
+ "There is always only one Cookie by name \"%s\"",
key
)
);
diff --git a/src/test/java/org/takes/facets/previous/RsPreviousTest.java b/src/test/java/org/takes/facets/previous/RsPreviousTest.java
new file mode 100644
index 000000000..214c28670
--- /dev/null
+++ b/src/test/java/org/takes/facets/previous/RsPreviousTest.java
@@ -0,0 +1,57 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014-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.
+ */
+package org.takes.facets.previous;
+
+import java.io.IOException;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.Test;
+import org.takes.rs.RsPrint;
+import org.takes.rs.RsText;
+
+/**
+ * Test case for {@link RsPrevious}.
+ * @author Yegor Bugayenko (yegor256@gmail.com)
+ * @version $Id$
+ * @since 0.2
+ */
+public final class RsPreviousTest {
+
+ /**
+ * RsPrevious can build a response.
+ * @throws IOException If some problem inside
+ */
+ @Test
+ public void buildsResponse() throws IOException {
+ MatcherAssert.assertThat(
+ new RsPrint(
+ new RsPrevious(new RsText(""), "/home")
+ ).print(),
+ Matchers.containsString(
+ "Set-Cookie: org.takes.facets.previous.TkPrevious=/home"
+ )
+ );
+ }
+
+}
diff --git a/src/test/java/org/takes/facets/previous/TkPreviousTest.java b/src/test/java/org/takes/facets/previous/TkPreviousTest.java
new file mode 100644
index 000000000..31dd41943
--- /dev/null
+++ b/src/test/java/org/takes/facets/previous/TkPreviousTest.java
@@ -0,0 +1,63 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014-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.
+ */
+package org.takes.facets.previous;
+
+import java.io.IOException;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.Test;
+import org.takes.rq.RqFake;
+import org.takes.rq.RqWithHeader;
+import org.takes.rs.RsPrint;
+import org.takes.tk.TkText;
+
+/**
+ * Test case for {@link TkPrevious}.
+ * @author Yegor Bugayenko (yegor256@gmail.com)
+ * @version $Id$
+ * @since 0.2
+ */
+public final class TkPreviousTest {
+
+ /**
+ * TkPrevious can redirect.
+ * @throws IOException If some problem inside
+ */
+ @Test
+ public void redirectsOnCookie() throws IOException {
+ MatcherAssert.assertThat(
+ new RsPrint(
+ new TkPrevious(new TkText("")).act(
+ new RqWithHeader(
+ new RqFake(),
+ "Cookie",
+ "org.takes.facets.previous.TkPrevious=/home"
+ )
+ )
+ ).print(),
+ Matchers.startsWith("HTTP/1.1 303 See Other")
+ );
+ }
+
+}
diff --git a/src/test/java/org/takes/facets/previous/package-info.java b/src/test/java/org/takes/facets/previous/package-info.java
new file mode 100644
index 000000000..03137a7ad
--- /dev/null
+++ b/src/test/java/org/takes/facets/previous/package-info.java
@@ -0,0 +1,32 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014-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.
+ */
+
+/**
+ * Previous, tests.
+ *
+ * @author Yegor Bugayenko (yegor256@gmail.com)
+ * @version $Id$
+ * @since 0.10
+ */
+package org.takes.facets.previous;