Skip to content

Commit 782a2b8

Browse files
authored
Merge pull request #4 from CrodiYa/add-item-requests-and-gateway
feat: add everything
2 parents 9942d3a + c6cd338 commit 782a2b8

109 files changed

Lines changed: 4268 additions & 188 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docker-compose.yaml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
services:
2+
gateway:
3+
build: gateway
4+
image: shareit-gateway
5+
container_name: shareit-gateway
6+
ports:
7+
- "8080:8080"
8+
depends_on:
9+
- server
10+
environment:
11+
- SHAREIT_SERVER_URL=http://server:9090
12+
13+
server:
14+
build: server
15+
image: shareit-server
16+
container_name: shareit-server
17+
ports:
18+
- "9090:9090"
19+
depends_on:
20+
- db
21+
environment:
22+
- SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/shareit
23+
- SPRING_DATASOURCE_USERNAME=shareit
24+
- SPRING_DATASOURCE_PASSWORD=shareit
25+
26+
db:
27+
image: postgres:16.1
28+
container_name: postgres
29+
ports:
30+
- "6541:5432"
31+
environment:
32+
- POSTGRES_PASSWORD=shareit
33+
- POSTGRES_USER=shareit
34+
- POSTGRES_DB=shareit
35+
healthcheck:
36+
test: pg_isready -q -d $$POSTGRES_DB -U $$POSTGRES_USER
37+
timeout: 5s
38+
interval: 5s
39+
retries: 10

gateway/Dockerfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
FROM amazoncorretto:21
2+
VOLUME /tmp
3+
ARG JAR_FILE=target/*.jar
4+
COPY ${JAR_FILE} app.jar
5+
ENTRYPOINT ["sh", "-c", "java ${JAVA_OPTS} -jar /app.jar"]

gateway/pom.xml

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>ru.practicum</groupId>
7+
<artifactId>shareit</artifactId>
8+
<version>0.0.1-SNAPSHOT</version>
9+
</parent>
10+
11+
<artifactId>gateway</artifactId>
12+
<version>0.0.1-SNAPSHOT</version>
13+
14+
<name>ShareIt Gateway</name>
15+
16+
<dependencies>
17+
<dependency>
18+
<groupId>org.springframework.boot</groupId>
19+
<artifactId>spring-boot-starter-web</artifactId>
20+
</dependency>
21+
22+
<dependency>
23+
<groupId>org.springframework.boot</groupId>
24+
<artifactId>spring-boot-starter-validation</artifactId>
25+
</dependency>
26+
27+
<dependency>
28+
<groupId>org.springframework.boot</groupId>
29+
<artifactId>spring-boot-starter-actuator</artifactId>
30+
</dependency>
31+
32+
<dependency>
33+
<groupId>org.hibernate.validator</groupId>
34+
<artifactId>hibernate-validator</artifactId>
35+
</dependency>
36+
37+
<dependency>
38+
<groupId>org.apache.httpcomponents.client5</groupId>
39+
<artifactId>httpclient5</artifactId>
40+
</dependency>
41+
42+
<dependency>
43+
<groupId>org.springframework.boot</groupId>
44+
<artifactId>spring-boot-configuration-processor</artifactId>
45+
<optional>true</optional>
46+
</dependency>
47+
48+
<dependency>
49+
<groupId>org.projectlombok</groupId>
50+
<artifactId>lombok</artifactId>
51+
<optional>true</optional>
52+
</dependency>
53+
54+
<dependency>
55+
<groupId>org.springframework.boot</groupId>
56+
<artifactId>spring-boot-starter-test</artifactId>
57+
<scope>test</scope>
58+
</dependency>
59+
</dependencies>
60+
61+
<build>
62+
<plugins>
63+
<plugin>
64+
<groupId>org.apache.maven.plugins</groupId>
65+
<artifactId>maven-checkstyle-plugin</artifactId>
66+
<version>${maven-checkstyle-plugin.version}</version>
67+
68+
<configuration>
69+
<failOnViolation>true</failOnViolation>
70+
<logViolationsToConsole>true</logViolationsToConsole>
71+
<includeTestSourceDirectory>true</includeTestSourceDirectory>
72+
<configLocation>checkstyle.xml</configLocation>
73+
</configuration>
74+
75+
<executions>
76+
<execution>
77+
<goals>
78+
<goal>check</goal>
79+
</goals>
80+
<phase>compile</phase>
81+
</execution>
82+
</executions>
83+
</plugin>
84+
<plugin>
85+
<groupId>org.springframework.boot</groupId>
86+
<artifactId>spring-boot-maven-plugin</artifactId>
87+
</plugin>
88+
</plugins>
89+
</build>
90+
91+
</project>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package ru.practicum.shareit;
2+
3+
public interface OnCreate {
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package ru.practicum.shareit;
2+
3+
public interface OnUpdate {
4+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package ru.practicum.shareit;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
6+
@SpringBootApplication
7+
public class ShareItGateway {
8+
9+
public static void main(String[] args) {
10+
SpringApplication.run(ShareItGateway.class, args);
11+
}
12+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package ru.practicum.shareit;
2+
3+
public class Util {
4+
public static final String USER_ID_HEADER = "X-Sharer-User-Id";
5+
6+
public static final String EMPTY_PATH = "";
7+
8+
public static final String USERS_PATH = "/users";
9+
public static final String ITEMS_PATH = "/items";
10+
public static final String BOOKING_PATH = "/bookings";
11+
public static final String REQUEST_PATH = "/requests";
12+
13+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package ru.practicum.shareit.client;
2+
3+
import jakarta.annotation.PostConstruct;
4+
import org.springframework.beans.factory.annotation.Value;
5+
import org.springframework.boot.web.client.RestTemplateBuilder;
6+
import org.springframework.http.*;
7+
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
8+
import org.springframework.lang.Nullable;
9+
import org.springframework.web.client.HttpStatusCodeException;
10+
import org.springframework.web.client.RestTemplate;
11+
import org.springframework.web.util.DefaultUriBuilderFactory;
12+
13+
import java.util.List;
14+
import java.util.Map;
15+
16+
public class BaseClient {
17+
18+
@Value("${shareit-server.url}")
19+
private String serverUrl;
20+
21+
private final String prefix;
22+
23+
protected RestTemplate rest;
24+
25+
@PostConstruct
26+
public void init() {
27+
RestTemplateBuilder builder = new RestTemplateBuilder();
28+
29+
this.rest = builder.uriTemplateHandler(new DefaultUriBuilderFactory(serverUrl + prefix))
30+
.requestFactory(() -> new HttpComponentsClientHttpRequestFactory())
31+
.build();
32+
}
33+
34+
public BaseClient(String prefix) {
35+
this.prefix = prefix;
36+
}
37+
38+
protected ResponseEntity<Object> get(String path) {
39+
return get(path, null, null);
40+
}
41+
42+
protected ResponseEntity<Object> get(String path, long userId) {
43+
return get(path, userId, null);
44+
}
45+
46+
protected ResponseEntity<Object> get(String path, Long userId, @Nullable Map<String, Object> parameters) {
47+
return makeAndSendRequest(HttpMethod.GET, path, userId, parameters, null);
48+
}
49+
50+
protected <T> ResponseEntity<Object> post(String path, T body) {
51+
return post(path, null, null, body);
52+
}
53+
54+
protected <T> ResponseEntity<Object> post(String path, long userId, T body) {
55+
return post(path, userId, null, body);
56+
}
57+
58+
protected <T> ResponseEntity<Object> post(String path, Long userId, @Nullable Map<String, Object> parameters, T body) {
59+
return makeAndSendRequest(HttpMethod.POST, path, userId, parameters, body);
60+
}
61+
62+
protected <T> ResponseEntity<Object> put(String path, long userId, T body) {
63+
return put(path, userId, null, body);
64+
}
65+
66+
protected <T> ResponseEntity<Object> put(String path, long userId, @Nullable Map<String, Object> parameters, T body) {
67+
return makeAndSendRequest(HttpMethod.PUT, path, userId, parameters, body);
68+
}
69+
70+
protected <T> ResponseEntity<Object> patch(String path, T body) {
71+
return patch(path, null, null, body);
72+
}
73+
74+
protected <T> ResponseEntity<Object> patch(String path, long userId) {
75+
return patch(path, userId, null, null);
76+
}
77+
78+
protected <T> ResponseEntity<Object> patch(String path, long userId, T body) {
79+
return patch(path, userId, null, body);
80+
}
81+
82+
protected <T> ResponseEntity<Object> patch(String path, long userId, Map<String, Object> parameters) {
83+
return patch(path, userId, parameters, null);
84+
}
85+
86+
protected <T> ResponseEntity<Object> patch(String path, Long userId, @Nullable Map<String, Object> parameters, T body) {
87+
return makeAndSendRequest(HttpMethod.PATCH, path, userId, parameters, body);
88+
}
89+
90+
protected ResponseEntity<Object> delete(String path) {
91+
return delete(path, null, null);
92+
}
93+
94+
protected ResponseEntity<Object> delete(String path, long userId) {
95+
return delete(path, userId, null);
96+
}
97+
98+
protected ResponseEntity<Object> delete(String path, Long userId, @Nullable Map<String, Object> parameters) {
99+
return makeAndSendRequest(HttpMethod.DELETE, path, userId, parameters, null);
100+
}
101+
102+
private <T> ResponseEntity<Object> makeAndSendRequest(HttpMethod method, String path, Long userId, @Nullable Map<String, Object> parameters, @Nullable T body) {
103+
HttpEntity<T> requestEntity = new HttpEntity<>(body, defaultHeaders(userId));
104+
105+
ResponseEntity<Object> shareitServerResponse;
106+
try {
107+
if (parameters != null) {
108+
shareitServerResponse = rest.exchange(path, method, requestEntity, Object.class, parameters);
109+
} else {
110+
shareitServerResponse = rest.exchange(path, method, requestEntity, Object.class);
111+
}
112+
} catch (HttpStatusCodeException e) {
113+
return ResponseEntity.status(e.getStatusCode()).body(e.getResponseBodyAsByteArray());
114+
}
115+
return prepareGatewayResponse(shareitServerResponse);
116+
}
117+
118+
private HttpHeaders defaultHeaders(Long userId) {
119+
HttpHeaders headers = new HttpHeaders();
120+
headers.setContentType(MediaType.APPLICATION_JSON);
121+
headers.setAccept(List.of(MediaType.APPLICATION_JSON));
122+
if (userId != null) {
123+
headers.set("X-Sharer-User-Id", String.valueOf(userId));
124+
}
125+
return headers;
126+
}
127+
128+
private static ResponseEntity<Object> prepareGatewayResponse(ResponseEntity<Object> response) {
129+
if (response.getStatusCode().is2xxSuccessful()) {
130+
return response;
131+
}
132+
133+
ResponseEntity.BodyBuilder responseBuilder = ResponseEntity.status(response.getStatusCode());
134+
135+
if (response.hasBody()) {
136+
return responseBuilder.body(response.getBody());
137+
}
138+
139+
return responseBuilder.build();
140+
}
141+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package ru.practicum.shareit.client;
2+
3+
import org.springframework.http.ResponseEntity;
4+
import org.springframework.stereotype.Component;
5+
import ru.practicum.shareit.dto.BookingDto;
6+
import ru.practicum.shareit.dto.BookingState;
7+
8+
import java.util.Collections;
9+
10+
import static ru.practicum.shareit.Util.BOOKING_PATH;
11+
import static ru.practicum.shareit.Util.EMPTY_PATH;
12+
13+
@Component
14+
public class BookingClient extends BaseClient {
15+
public BookingClient() {
16+
super(BOOKING_PATH);
17+
}
18+
19+
public ResponseEntity<Object> createBooking(Long userId, BookingDto dto) {
20+
if (!dto.getStart().isBefore(dto.getEnd())) {
21+
return ResponseEntity.badRequest().build();
22+
}
23+
24+
return post(EMPTY_PATH, userId, dto);
25+
}
26+
27+
public ResponseEntity<Object> updateBookingStatus(Long userId, Long bookingId, Boolean approved) {
28+
return patch("/" + bookingId + "?approved={approved}",
29+
userId,
30+
Collections.singletonMap("approved", approved));
31+
}
32+
33+
public ResponseEntity<Object> getBooking(Long userId, Long bookingId) {
34+
return get("/" + bookingId, userId);
35+
}
36+
37+
public ResponseEntity<Object> findByBookerAndState(Long bookerId, BookingState state) {
38+
return get("?state={state}", bookerId, Collections.singletonMap("state", state));
39+
}
40+
41+
public ResponseEntity<Object> findByOwnerAndState(Long ownerId, BookingState state) {
42+
return get("/owner?state={state}", ownerId, Collections.singletonMap("state", state));
43+
}
44+
}

0 commit comments

Comments
 (0)