Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
c6ee97c
Signed-off-by: aicodeguard <zifeiyu19980606@gmail.com>
aicodeguard Oct 11, 2025
31a2383
增量测试
aicodeguard Nov 10, 2025
e14afbf
Signed-off-by: aicodeguard <zifeiyu19980606@gmail.com>
aicodeguard Nov 10, 2025
0b29ae0
Signed-off-by: aicodeguard <zifeiyu19980606@gmail.com>
aicodeguard Nov 10, 2025
184d976
Signed-off-by: aicodeguard <zifeiyu19980606@gmail.com>
aicodeguard Nov 10, 2025
7783894
Signed-off-by: aicodeguard <zifeiyu19980606@gmail.com>
aicodeguard Nov 10, 2025
eb0bf1d
Signed-off-by: aicodeguard <zifeiyu19980606@gmail.com>
aicodeguard Nov 10, 2025
71f5800
Signed-off-by: aicodeguard <zifeiyu19980606@gmail.com>
aicodeguard Nov 10, 2025
b3b373d
Signed-off-by: aicodeguard <zifeiyu19980606@gmail.com>
aicodeguard Nov 10, 2025
9a7c204
Signed-off-by: aicodeguard <zifeiyu19980606@gmail.com>
aicodeguard Nov 10, 2025
94fa3a1
Signed-off-by: aicodeguard <zifeiyu19980606@gmail.com>
aicodeguard Nov 10, 2025
82f2246
Signed-off-by: aicodeguard <zifeiyu19980606@gmail.com>
aicodeguard Nov 10, 2025
82abb57
Signed-off-by: aicodeguard <zifeiyu19980606@gmail.com>
aicodeguard Nov 10, 2025
2ed0f07
Signed-off-by: aicodeguard <zifeiyu19980606@gmail.com>
aicodeguard Nov 11, 2025
ee804a6
Signed-off-by: aicodeguard <zifeiyu19980606@gmail.com>
aicodeguard Nov 11, 2025
fa38b24
Signed-off-by: aicodeguard <zifeiyu19980606@gmail.com>
aicodeguard Nov 11, 2025
f01aac1
Signed-off-by: aicodeguard <zifeiyu19980606@gmail.com>
aicodeguard Nov 11, 2025
174afa7
Signed-off-by: aicodeguard <zifeiyu19980606@gmail.com>
aicodeguard Nov 11, 2025
91c9b1b
Signed-off-by: aicodeguard <zifeiyu19980606@gmail.com>
aicodeguard Nov 11, 2025
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
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/aliyun/api/gateway/demo/Request.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import com.aliyun.api.gateway.demo.enums.Method;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

Expand Down Expand Up @@ -195,4 +196,7 @@ public List<String> getSignHeaderPrefixList() {
public void setSignHeaderPrefixList(List<String> signHeaderPrefixList) {
this.signHeaderPrefixList = signHeaderPrefixList;
}
public void setSignHeaderPrefixList(String signHeaderPrefixList) {
this.signHeaderPrefixList = Arrays.asList(signHeaderPrefixList.split(","));
}
Comment on lines +199 to +201
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Add null and empty string validation before splitting to prevent creating a list with a single empty element. Trim whitespace from each element to avoid issues with malformed input.

Suggested change
public void setSignHeaderPrefixList(String signHeaderPrefixList) {
this.signHeaderPrefixList = Arrays.asList(signHeaderPrefixList.split(","));
}
public void setSignHeaderPrefixList(String signHeaderPrefixList) {
if (signHeaderPrefixList == null || signHeaderPrefixList.trim().isEmpty()) {
this.signHeaderPrefixList = new ArrayList<>();
return;
}
this.signHeaderPrefixList = Arrays.stream(signHeaderPrefixList.split(","))
.map(String::trim)
.filter(s -> !s.isEmpty())
.collect(Collectors.toList());
}

}
95 changes: 95 additions & 0 deletions src/main/java/com/aliyun/api/gateway/demo/service/JiraConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.aliyun.api.gateway.demo.service;

/**
* Jira 配置类
*/
public class JiraConfig {
/**
* Jira 服务器地址(例如:https://your-domain.atlassian.net)
*/
private String jiraBaseUrl;

/**
* Jira 用户邮箱
*/
private String username;

/**
* Jira API Token
*/
private String apiToken;
Comment on lines +28 to +38
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Mark sensitive fields as transient to prevent serialization and add a toString() method that masks credentials to prevent accidental logging of plaintext secrets.

Suggested change
private String jiraBaseUrl;
/**
* Jira 用户邮箱
*/
private String username;
/**
* Jira API Token
*/
private String apiToken;
private String jiraBaseUrl;
/**
* Jira 用户邮箱
*/
private transient String username;
/**
* Jira API Token
*/
private transient String apiToken;


/**
* 请求超时时间(毫秒)
*/
private int timeout;

public JiraConfig() {
this.timeout = 30000; // 默认30秒
}

public JiraConfig(String jiraBaseUrl, String username, String apiToken) {
this.jiraBaseUrl = jiraBaseUrl;
this.username = username;
this.apiToken = apiToken;
this.timeout = 30000;
}

public JiraConfig(String jiraBaseUrl, String username, String apiToken, int timeout) {
this.jiraBaseUrl = jiraBaseUrl;
this.username = username;
this.apiToken = apiToken;
this.timeout = timeout;
}

public String getJiraBaseUrl() {
return jiraBaseUrl;
}

public void setJiraBaseUrl(String jiraBaseUrl) {
this.jiraBaseUrl = jiraBaseUrl;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getApiToken() {
return apiToken;
}

public void setApiToken(String apiToken) {
this.apiToken = apiToken;
}

public int getTimeout() {
return timeout;
}

public void setTimeout(int timeout) {
this.timeout = timeout;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.aliyun.api.gateway.demo.service;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
* Jira 配置加载器
* 从配置文件或环境变量中加载 Jira 配置
*/
public class JiraConfigLoader {

private static final String DEFAULT_CONFIG_FILE = "jira-config.properties";

/**
* 从默认配置文件加载配置
* @return JiraConfig 对象
* @throws IOException
*/
public static JiraConfig loadFromFile() throws IOException {
return loadFromFile(DEFAULT_CONFIG_FILE);
}

/**
* 从指定配置文件加载配置
* @param configFile 配置文件路径
* @return JiraConfig 对象
* @throws IOException
*/
public static JiraConfig loadFromFile(String configFile) throws IOException {
Properties props = new Properties();

// 尝试从文件系统加载
try (InputStream input = new FileInputStream(configFile)) {
props.load(input);
} catch (IOException e) {
// 尝试从 classpath 加载
try (InputStream input = JiraConfigLoader.class.getClassLoader()
.getResourceAsStream(configFile)) {
if (input == null) {
throw new IOException("无法找到配置文件: " + configFile);
}
props.load(input);
}
}

return createConfigFromProperties(props);
}

/**
* 从环境变量加载配置
* @return JiraConfig 对象
*/
public static JiraConfig loadFromEnv() {
String baseUrl = System.getenv("JIRA_BASE_URL");
String username = System.getenv("JIRA_USERNAME");
String apiToken = System.getenv("JIRA_API_TOKEN");
String timeoutStr = System.getenv("JIRA_TIMEOUT");

if (baseUrl == null || username == null || apiToken == null) {
throw new IllegalStateException(
"缺少必要的环境变量: JIRA_BASE_URL, JIRA_USERNAME, JIRA_API_TOKEN"
);
}
Comment on lines +74 to +83
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Remove explicit listing of missing environment variable names from the exception message to avoid information disclosure. Use a generic message that does not reveal internal configuration details.

Suggested change
String baseUrl = System.getenv("JIRA_BASE_URL");
String username = System.getenv("JIRA_USERNAME");
String apiToken = System.getenv("JIRA_API_TOKEN");
String timeoutStr = System.getenv("JIRA_TIMEOUT");
if (baseUrl == null || username == null || apiToken == null) {
throw new IllegalStateException(
"缺少必要的环境变量: JIRA_BASE_URL, JIRA_USERNAME, JIRA_API_TOKEN"
);
}
String baseUrl = System.getenv("JIRA_BASE_URL");
String username = System.getenv("JIRA_USERNAME");
String apiToken = System.getenv("JIRA_API_TOKEN");
String timeoutStr = System.getenv("JIRA_TIMEOUT");
if (baseUrl == null || username == null || apiToken == null) {
throw new IllegalStateException(
"Required Jira configuration environment variables are missing"
);
}


int timeout = 30000; // 默认30秒
if (timeoutStr != null && !timeoutStr.isEmpty()) {
try {
timeout = Integer.parseInt(timeoutStr);
} catch (NumberFormatException e) {
System.err.println("无效的超时时间配置,使用默认值: 30000ms");
}
}

return new JiraConfig(baseUrl, username, apiToken, timeout);
}

/**
* 从 Properties 对象创建 JiraConfig
* @param props Properties 对象
* @return JiraConfig 对象
*/
private static JiraConfig createConfigFromProperties(Properties props) {
String baseUrl = props.getProperty("jira.base.url");
String username = props.getProperty("jira.username");
String apiToken = props.getProperty("jira.api.token");
String timeoutStr = props.getProperty("jira.timeout", "30000");

if (baseUrl == null || username == null || apiToken == null) {
throw new IllegalStateException(
"配置文件缺少必要的属性: jira.base.url, jira.username, jira.api.token"
);
}

int timeout = 30000;
try {
timeout = Integer.parseInt(timeoutStr);
} catch (NumberFormatException e) {
System.err.println("无效的超时时间配置,使用默认值: 30000ms");
}

return new JiraConfig(baseUrl, username, apiToken, timeout);
}

/**
* 优先从环境变量加载,如果失败则从配置文件加载
* @return JiraConfig 对象
* @throws IOException
*/
public static JiraConfig load() throws IOException {
try {
return loadFromEnv();
} catch (IllegalStateException e) {
System.out.println("从环境变量加载失败,尝试从配置文件加载...");
return loadFromFile();
}
}
}

Loading