Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add possibility to pass request headers to HttpClient #791

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public class Settings {
public String restResponseType = null;
public String restOptionsType = null;
public boolean restOptionsTypeIsGeneric;
public boolean restHeaderArgumentsParsed;
private List<RestApplicationParser.Factory> restApplicationParserFactories;
public TypeProcessor customTypeProcessor = null;
public boolean sortDeclarations = false;
Expand Down Expand Up @@ -759,6 +760,10 @@ public void setRestOptionsType(String restOptionsType) {
}
}

public void setRestHeaderArgumentsParsed(boolean restHeaderArgumentsParsed) {
this.restHeaderArgumentsParsed = restHeaderArgumentsParsed;
}

public List<RestApplicationParser.Factory> getRestApplicationParserFactories() {
if (restApplicationParserFactories == null) {
final List<RestApplicationParser.Factory> factories = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
import cz.habarta.typescript.generator.parser.PropertyModel;
import cz.habarta.typescript.generator.parser.RestApplicationModel;
import cz.habarta.typescript.generator.parser.RestMethodModel;
import cz.habarta.typescript.generator.parser.RestQueryParam;
import cz.habarta.typescript.generator.parser.RestParam;
import cz.habarta.typescript.generator.type.JTypeWithNullability;
import cz.habarta.typescript.generator.util.GenericsResolver;
import cz.habarta.typescript.generator.util.Pair;
Expand Down Expand Up @@ -622,6 +622,7 @@ private void createRestClients(TsModel tsModel, SymbolTable symbolTable, List<Re
new TsProperty("queryParams", new TsType.OptionalType(TsType.Any)),
new TsProperty("data", new TsType.OptionalType(TsType.Any)),
new TsProperty("copyFn", new TsType.OptionalType(new TsType.FunctionType(Arrays.asList(new TsParameter("data", returnGenericVariable)), returnGenericVariable))),
new TsProperty("headers", new TsType.OptionalType(TsType.Any)),
optionsType != null ? new TsProperty("options", new TsType.OptionalType(optionsType)) : null
))
), new TsType.GenericReferenceType(responseSymbol, returnGenericVariable), null, null)
Expand Down Expand Up @@ -728,57 +729,14 @@ private TsMethodModel processRestMethod(TsModel tsModel, SymbolTable symbolTable
parameters.add(processParameter(symbolTable, method, method.getEntityParam()));
}
// query params
final List<RestQueryParam> queryParams = method.getQueryParams();
final TsParameterModel queryParameter;
if (queryParams != null && !queryParams.isEmpty()) {
final List<TsType> types = new ArrayList<>();
if (queryParams.stream().anyMatch(param -> param instanceof RestQueryParam.Map)) {
types.add(new TsType.IndexedArrayType(TsType.String, TsType.Any));
} else {
final List<TsProperty> currentSingles = new ArrayList<>();
final Runnable flushSingles = () -> {
if (!currentSingles.isEmpty()) {
types.add(new TsType.ObjectType(currentSingles));
currentSingles.clear();
}
};
for (RestQueryParam restQueryParam : queryParams) {
if (restQueryParam instanceof RestQueryParam.Single) {
final MethodParameterModel queryParam = ((RestQueryParam.Single) restQueryParam).getQueryParam();
final TsType type = typeFromJava(symbolTable, queryParam.getType(), method.getName(), method.getOriginClass());
currentSingles.add(new TsProperty(queryParam.getName(), restQueryParam.required ? type : new TsType.OptionalType(type)));
}
if (restQueryParam instanceof RestQueryParam.Bean) {
final BeanModel queryBean = ((RestQueryParam.Bean) restQueryParam).getBean();
flushSingles.run();
final Symbol queryParamsSymbol = symbolTable.getSymbol(queryBean.getOrigin(), "QueryParams");
if (tsModel.getBean(queryParamsSymbol) == null) {
tsModel.getBeans().add(new TsBeanModel(
queryBean.getOrigin(),
TsBeanCategory.Data,
/*isClass*/false,
queryParamsSymbol,
/*typeParameters*/null,
/*parent*/null,
/*extendsList*/null,
/*implementsList*/null,
processProperties(symbolTable, null, queryBean),
/*constructor*/null,
/*methods*/null,
/*comments*/null
));
}
types.add(new TsType.ReferenceType(queryParamsSymbol));
}
}
flushSingles.run();
}
boolean allQueryParamsOptional = queryParams.stream().noneMatch(queryParam -> queryParam.required);
TsType.IntersectionType queryParamType = new TsType.IntersectionType(types);
queryParameter = new TsParameterModel("queryParams", allQueryParamsOptional ? new TsType.OptionalType(queryParamType) : queryParamType);
final TsParameterModel queryParameter = convertRestParams(method.getQueryParams(), symbolTable, method, tsModel, "queryParams", "QueryParams");
if(queryParameter != null){
parameters.add(queryParameter);
} else {
queryParameter = null;
}
// body params
final TsParameterModel headersParameter = convertRestParams(method.getHeaders(), symbolTable, method, tsModel, "headers", "Headers");
if(headersParameter != null){
parameters.add(headersParameter);
}
if (optionsType != null) {
final TsParameterModel optionsParameter = new TsParameterModel("options", new TsType.OptionalType(optionsType));
Expand Down Expand Up @@ -808,6 +766,7 @@ private TsMethodModel processRestMethod(TsModel tsModel, SymbolTable symbolTable
new TsPropertyDefinition("url", processPathTemplate(pathTemplate)),
queryParameter != null ? new TsPropertyDefinition("queryParams", new TsIdentifierReference("queryParams")) : null,
method.getEntityParam() != null ? new TsPropertyDefinition("data", new TsIdentifierReference(method.getEntityParam().getName())) : null,
headersParameter != null ? new TsPropertyDefinition("headers", new TsIdentifierReference("headers")) : null,
optionsType != null ? new TsPropertyDefinition("options", new TsIdentifierReference("options")) : null
)
)
Expand All @@ -820,6 +779,57 @@ private TsMethodModel processRestMethod(TsModel tsModel, SymbolTable symbolTable
return tsMethodModel;
}

private TsParameterModel convertRestParams(List<RestParam> restParams, SymbolTable symbolTable, RestMethodModel method, TsModel tsModel, String parameterName, String beanSuffix){
if (restParams == null || restParams.isEmpty()){
return null;
}
final List<TsType> types = new ArrayList<>();
if (restParams.stream().anyMatch(param -> param instanceof RestParam.Map)) {
types.add(new TsType.IndexedArrayType(TsType.String, TsType.Any));
} else {
final List<TsProperty> currentSingles = new ArrayList<>();
final Runnable flushSingles = () -> {
if (!currentSingles.isEmpty()) {
types.add(new TsType.ObjectType(currentSingles));
currentSingles.clear();
}
};
for (RestParam restParam : restParams) {
if (restParam instanceof RestParam.Single) {
final MethodParameterModel restParamMethodParameterModel = ((RestParam.Single) restParam).getRestParam();
final TsType type = typeFromJava(symbolTable, restParamMethodParameterModel.getType(), method.getName(), method.getOriginClass());
currentSingles.add(new TsProperty(restParamMethodParameterModel.getName(), restParam.required ? type : new TsType.OptionalType(type)));
}
if (restParam instanceof RestParam.Bean) {
final BeanModel paramBean = ((RestParam.Bean) restParam).getBean();
flushSingles.run();
final Symbol paramsSymbol = symbolTable.getSymbol(paramBean.getOrigin(), beanSuffix);
if (tsModel.getBean(paramsSymbol) == null) {
tsModel.getBeans().add(new TsBeanModel(
paramBean.getOrigin(),
TsBeanCategory.Data,
/*isClass*/false,
paramsSymbol,
/*typeParameters*/null,
/*parent*/null,
/*extendsList*/null,
/*implementsList*/null,
processProperties(symbolTable, null, paramBean),
/*constructor*/null,
/*methods*/null,
/*comments*/null
));
}
types.add(new TsType.ReferenceType(paramsSymbol));
}
}
flushSingles.run();
}
boolean allParamsOptional = restParams.stream().noneMatch(param -> param.required);
TsType.IntersectionType paramType = new TsType.IntersectionType(types);
return new TsParameterModel(parameterName, allParamsOptional ? new TsType.OptionalType(paramType) : paramType);
}

private TsParameterModel processParameter(SymbolTable symbolTable, MethodModel method, MethodParameterModel parameter) {
final String parameterName = parameter.getName();
final TsType parameterType = typeFromJava(symbolTable, parameter.getType(), method.getName(), method.getOriginClass());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,25 +174,47 @@ private void parseResourceMethod(Result result, ResourceContext context, Class<?
}
}
// query parameters
final List<RestQueryParam> queryParams = new ArrayList<>();
final List<RestParam> queryParams = new ArrayList<>();
for (Parameter param : method.getParameters()) {
final QueryParam queryParamAnnotation = getRsAnnotation(param, QueryParam.class);
if (queryParamAnnotation != null) {
queryParams.add(new RestQueryParam.Single(new MethodParameterModel(queryParamAnnotation.value(), param.getParameterizedType()), false));
queryParams.add(new RestParam.Single(new MethodParameterModel(queryParamAnnotation.value(), param.getParameterizedType()), false));
foundType(result, param.getParameterizedType(), resourceClass, method.getName());
}
final BeanParam beanParamAnnotation = getRsAnnotation(param, BeanParam.class);
if (beanParamAnnotation != null) {
final Class<?> beanParamClass = param.getType();
final BeanModel paramBean = getQueryParameters(beanParamClass);
if (paramBean != null) {
queryParams.add(new RestQueryParam.Bean(paramBean));
queryParams.add(new RestParam.Bean(paramBean));
for (PropertyModel property : paramBean.getProperties()) {
foundType(result, property.getType(), beanParamClass, property.getName());
}
}
}
}
// header parameters
final List<RestParam> headers = new ArrayList<>();
if(settings.restHeaderArgumentsParsed){
for (Parameter param : method.getParameters()) {
final HeaderParam headerParamAnnotation = getRsAnnotation(param, HeaderParam.class);
if (headerParamAnnotation != null) {
headers.add(new RestParam.Single(new MethodParameterModel(headerParamAnnotation.value(), param.getParameterizedType()), false));
foundType(result, param.getParameterizedType(), resourceClass, method.getName());
}
final BeanParam beanParamAnnotation = getRsAnnotation(param, BeanParam.class);
if (beanParamAnnotation != null) {
final Class<?> beanParamClass = param.getType();
final BeanModel paramBean = getHeaderParameters(beanParamClass);
if (paramBean != null) {
headers.add(new RestParam.Bean(paramBean));
for (PropertyModel property : paramBean.getProperties()) {
foundType(result, property.getType(), beanParamClass, property.getName());
}
}
}
}
}
// JAX-RS specification - 3.3.2.1 Entity Parameters
final List<Type> parameterTypes = settings.getTypeParser().getMethodParameterTypes(method);
final List<Pair<Parameter, Type>> parameters = Utils.zip(Arrays.asList(method.getParameters()), parameterTypes);
Expand Down Expand Up @@ -234,7 +256,7 @@ private void parseResourceMethod(Result result, ResourceContext context, Class<?
final List<String> comments = Swagger.getOperationComments(swaggerOperation);
// create method
model.getMethods().add(new RestMethodModel(resourceClass, method.getName(), resolvedModelReturnType, method,
context.rootResource, httpMethod.value(), context.path, pathParams, queryParams, entityParameter, comments));
context.rootResource, httpMethod.value(), context.path, pathParams, queryParams, entityParameter, comments, headers));
}
// JAX-RS specification - 3.4.1 Sub Resources
if (pathAnnotation != null && httpMethod == null) {
Expand Down Expand Up @@ -282,6 +304,36 @@ private static BeanModel getQueryParameters(Class<?> paramBean) {
}
}

private static BeanModel getHeaderParameters(Class<?> paramBean) {
final List<PropertyModel> properties = new ArrayList<>();
final List<Field> fields = Utils.getAllFields(paramBean);
for (Field field : fields) {
final HeaderParam annotation = getRsAnnotation(field, HeaderParam.class);
if (annotation != null) {
properties.add(new PropertyModel(annotation.value(), field.getGenericType(), /*optional*/true, null, field, null, null, null));
}
}
try {
final BeanInfo beanInfo = Introspector.getBeanInfo(paramBean);
for (PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors()) {
final Method writeMethod = propertyDescriptor.getWriteMethod();
if (writeMethod != null) {
final HeaderParam annotation = getRsAnnotation(writeMethod, HeaderParam.class);
if (annotation != null) {
properties.add(new PropertyModel(annotation.value(), propertyDescriptor.getPropertyType(), /*optional*/true, null, writeMethod, null, null, null));
}
}
}
} catch (IntrospectionException e) {
TypeScriptGenerator.getLogger().warning(String.format("Cannot introspect '%s' class: " + e.getMessage(), paramBean));
}
if (properties.isEmpty()) {
return null;
} else {
return new BeanModel(paramBean, null, null, null, null, null, properties, null);
}
}

private MethodParameterModel getEntityParameter(Class<?> resourceClass, Method method, List<Pair<Parameter, Type>> parameters) {
for (Pair<Parameter, Type> pair : parameters) {
if (!Utils.hasAnyAnnotation(annotationClass -> pair.getValue1().getAnnotation(annotationClass), Arrays.asList(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,21 @@ public class RestMethodModel extends MethodModel {
private final String httpMethod;
private final String path;
private final List<MethodParameterModel> pathParams;
private final List<RestQueryParam> queryParams;
private final List<RestParam> queryParams;
private final MethodParameterModel entityParam;
private final List<RestParam> headers;

public RestMethodModel(Class<?> originClass, String name, Type returnType, Method originalMethod,
Class<?> rootResource, String httpMethod, String path, List<MethodParameterModel> pathParams, List<RestQueryParam> queryParams, MethodParameterModel entityParam,
List<String> comments) {
Class<?> rootResource, String httpMethod, String path, List<MethodParameterModel> pathParams, List<RestParam> queryParams, MethodParameterModel entityParam,
List<String> comments, List<RestParam> headers) {
super(originClass, name, null, returnType, originalMethod, comments);
this.rootResource = rootResource;
this.httpMethod = httpMethod;
this.path = path;
this.pathParams = pathParams;
this.queryParams = queryParams;
this.entityParam = entityParam;
this.headers = headers;
}

public Class<?> getRootResource() {
Expand All @@ -43,17 +45,21 @@ public List<MethodParameterModel> getPathParams() {
return pathParams;
}

public List<RestQueryParam> getQueryParams() {
public List<RestParam> getQueryParams() {
return queryParams;
}

public MethodParameterModel getEntityParam() {
return entityParam;
}

public List<RestParam> getHeaders() {
return headers;
}

@Override
public RestMethodModel withComments(List<String> comments) {
return new RestMethodModel(originClass, name, returnType, originalMethod, rootResource, httpMethod, path, pathParams, queryParams, entityParam, comments);
return new RestMethodModel(originClass, name, returnType, originalMethod, rootResource, httpMethod, path, pathParams, queryParams, entityParam, comments, headers);
}

}
Loading