Render recipe URLs with all search parameters
This patch switches from using crawlUrl() to using the /go/ route and appends all search parameters to said urls following the idea outlined in b31fb8d995
- Id
- 170eb16f126a18afb0557e582e10f6f7d677f2f1
- Author
- Caio
- Commit time
- 2019-02-18T18:16:05-03:00
Modified pom.xml
<resilience4j.version>0.13.2</resilience4j.version>
<chronicle.version>3.17.0</chronicle.version>
<jsoup.version>1.11.3</jsoup.version>
- <tablier.version>0.2.0</tablier.version>
+ <tablier.version>0.2.1</tablier.version>
</properties>
<dependencyManagement>
Modified src/main/java/co/caio/cerberus/boot/ModelView.java
package co.caio.cerberus.boot;
import co.caio.cerberus.db.RecipeMetadata;
import co.caio.cerberus.db.RecipeMetadataDatabase;
import co.caio.cerberus.model.SearchQuery;
-import co.caio.cerberus.model.SearchQuery.RangedSpec;
import co.caio.cerberus.model.SearchResult;
import co.caio.cerberus.model.SearchResultRecipe;
import co.caio.tablier.model.ErrorInfo;
import com.fizzed.rocker.RockerModel;
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
+import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
@Component
private static final PageInfo defaultErrorPage =
new PageInfo.Builder().title(ERROR_PAGE_TITLE).build();
private static final String DEFAULT_UNKNOWN_ERROR_SUBTITLE = "Unknown Error Cause";
- private static final RangedSpec unselectedRange = RangedSpec.of(0, 0);
private final int pageSize;
private final RecipeMetadataDatabase db;
}
}
+ static final String GO_SLUG_ID_PATH = "/go/{slug}/{recipeId}";
+
RockerModel renderSearch(
SearchQuery query, SearchResult result, UriComponentsBuilder uriBuilder) {
boolean isLastPage = query.offset() + pageSize >= result.totalHits();
int currentPage = (query.offset() / pageSize) + 1;
+ var recipeGoUriComponents =
+ uriBuilder.cloneBuilder().replacePath(GO_SLUG_ID_PATH).encode().build();
+
var searchBuilder =
new SearchResultsInfo.Builder()
.paginationStart(query.offset() + 1)
.paginationEnd(result.recipes().size() + query.offset())
.numMatching(result.totalHits());
-
- uriBuilder.fragment("results");
if (!isLastPage) {
searchBuilder.nextPageHref(
uriBuilder.replaceQueryParam("page", currentPage - 1).build().toUriString());
}
- searchBuilder.recipes(renderRecipes(result.recipes()));
+ searchBuilder.recipes(renderRecipes(result.recipes(), recipeGoUriComponents));
// Sidebar links always lead to the first page
uriBuilder.replaceQueryParam("page");
.count();
}
- private Iterable<RecipeInfo> renderRecipes(List<SearchResultRecipe> recipes) {
+ private Iterable<RecipeInfo> renderRecipes(
+ List<SearchResultRecipe> recipes, UriComponents uriComponents) {
var recipeIds = recipes.stream().map(SearchResultRecipe::recipeId).collect(Collectors.toList());
return db.findAllById(recipeIds)
.stream()
- .map(RecipeMetadataRecipeInfoAdapter::new)
+ .map(r -> new RecipeMetadataRecipeInfoAdapter(r, uriComponents))
.collect(Collectors.toList());
}
return recipe;
}
- RockerModel renderSingleRecipe(long recipeId, String slug) {
+ RockerModel renderSingleRecipe(long recipeId, String slug, UriComponentsBuilder builder) {
var recipe = fetchRecipe(recipeId, slug);
return Recipe.template(
defaultSite,
new PageInfo.Builder().title(recipe.getName()).build(),
defaultSearchForm,
- new RecipeMetadataRecipeInfoAdapter(recipe));
+ new RecipeMetadataRecipeInfoAdapter(
+ recipe, builder.replacePath(GO_SLUG_ID_PATH).encode().build()));
}
static class RecipeMetadataRecipeInfoAdapter implements RecipeInfo {
private final RecipeMetadata metadata;
+ private final String goUrl;
- RecipeMetadataRecipeInfoAdapter(RecipeMetadata metadata) {
+ RecipeMetadataRecipeInfoAdapter(RecipeMetadata metadata, UriComponents uriComponents) {
this.metadata = metadata;
+ this.goUrl =
+ uriComponents
+ .expand(Map.of("slug", metadata.getSlug(), "recipeId", metadata.getRecipeId()))
+ .toUriString();
}
@Override
}
@Override
- public String crawlUrl() {
- return metadata.getCrawlUrl();
+ public String goUrl() {
+ return goUrl;
}
@Override
- public String slug() {
- return String.format("%s/%d", metadata.getSlug(), metadata.getRecipeId());
+ public String infoUrl() {
+ return goUrl.replace("/go/", "/recipe/");
}
@Override
Modified src/main/java/co/caio/cerberus/boot/RequestHandler.java
var recipeId = Long.parseLong(request.pathVariable("recipeId"));
return ServerResponse.ok()
.contentType(MediaType.TEXT_HTML)
- .body(BodyInserters.fromObject(modelView.renderSingleRecipe(recipeId, slug)));
+ .body(
+ BodyInserters.fromObject(
+ modelView.renderSingleRecipe(
+ recipeId, slug, UriComponentsBuilder.fromUri(request.uri()))));
}
public Mono<ServerResponse> go(ServerRequest request) {
Modified src/test/java/co/caio/cerberus/boot/ModelViewTest.java
assertTrue(doc.title().startsWith(ModelView.SEARCH_PAGE_TITLE));
- assertTrue(doc.selectFirst("nav.pagination a.pagination-previous").attr("href").contains("page=1"));
+ assertTrue(
+ doc.selectFirst("nav.pagination a.pagination-previous").attr("href").contains("page=1"));
assertTrue(doc.selectFirst("nav.pagination a.pagination-next").attr("href").contains("page=3"));
}
assertTrue(doc.title().startsWith(ModelView.SEARCH_PAGE_TITLE));
- assertTrue(doc.selectFirst("nav.pagination a.pagination-previous").attr("href").contains("page=1"));
+ assertTrue(
+ doc.selectFirst("nav.pagination a.pagination-previous").attr("href").contains("page=1"));
assertTrue(doc.selectFirst("nav.pagination a.pagination-next").attr("href").isEmpty());
}
var recipe = Util.getSampleRecipes().limit(1).findFirst().orElseThrow();
assertThrows(
RecipeNotFoundError.class,
- () -> modelView.renderSingleRecipe(recipe.recipeId(), "incorrect slug"));
+ () ->
+ modelView.renderSingleRecipe(
+ recipe.recipeId(), "incorrect slug", UriComponentsBuilder.newInstance()));
}
@Test
void incorrectIdYieldsNotFound() {
var recipe = Util.getSampleRecipes().limit(1).findFirst().orElseThrow();
- assertThrows(RecipeNotFoundError.class, () -> modelView.renderSingleRecipe(213, recipe.slug()));
+ assertThrows(
+ RecipeNotFoundError.class,
+ () -> modelView.renderSingleRecipe(213, recipe.slug(), UriComponentsBuilder.newInstance()));
}
@Test
void renderSingleRecipe() {
var recipe = Util.getSampleRecipes().limit(1).findFirst().orElseThrow();
- var doc = parseOutput(modelView.renderSingleRecipe(recipe.recipeId(), recipe.slug()));
+ var doc =
+ parseOutput(
+ modelView.renderSingleRecipe(
+ recipe.recipeId(), recipe.slug(), UriComponentsBuilder.newInstance()));
assertTrue(doc.title().startsWith(recipe.name()));
}
}